diff options
| author | Michael Biebl <biebl@debian.org> | 2022-02-14 19:23:28 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2022-02-14 19:23:28 +0100 |
| commit | 2f94dba7385fd0e0ef19a06eb4a2fcf6c43d7946 (patch) | |
| tree | e2222f5577115985dd52044d2991253403cdd952 /src/core/devices | |
| parent | 88c227d90a6b7b388c5c85d72802a0ca8f05ed5c (diff) | |
New upstream version 1.35.91 upstream/1.35.91
Diffstat (limited to 'src/core/devices')
80 files changed, 10175 insertions, 10653 deletions
diff --git a/src/core/devices/adsl/nm-atm-manager.c b/src/core/devices/adsl/nm-atm-manager.c index bd9ed8cc..cc8d37e6 100644 --- a/src/core/devices/adsl/nm-atm-manager.c +++ b/src/core/devices/adsl/nm-atm-manager.c @@ -27,7 +27,7 @@ typedef struct { NMUdevClient *udev_client; - GSList * devices; + GSList *devices; } NMAtmManagerPrivate; typedef struct { @@ -51,7 +51,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES( NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_ADSL_SETTING_NAME)); G_MODULE_EXPORT NMDeviceFactory * - nm_device_factory_create(GError **error) +nm_device_factory_create(GError **error) { return g_object_new(NM_TYPE_ATM_MANAGER, NULL); } @@ -62,7 +62,7 @@ static gboolean dev_get_attrs(struct udev_device *udev_device, const char **out_path, char **out_driver) { struct udev_device *parent = NULL; - const char * driver, *path; + const char *driver, *path; g_return_val_if_fail(udev_device != NULL, FALSE); g_return_val_if_fail(out_path != NULL, FALSE); @@ -91,7 +91,7 @@ dev_get_attrs(struct udev_device *udev_device, const char **out_path, char **out static void device_destroyed(gpointer user_data, GObject *dead) { - NMAtmManager * self = NM_ATM_MANAGER(user_data); + NMAtmManager *self = NM_ATM_MANAGER(user_data); NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self); priv->devices = g_slist_remove(priv->devices, dead); @@ -101,11 +101,11 @@ static void adsl_add(NMAtmManager *self, struct udev_device *udev_device) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self); - const char * ifname, *sysfs_path = NULL; - char * driver = NULL; - gs_free char * atm_index_path = NULL; + const char *ifname, *sysfs_path = NULL; + char *driver = NULL; + gs_free char *atm_index_path = NULL; int atm_index; - NMDevice * device; + NMDevice *device; g_return_if_fail(udev_device != NULL); @@ -153,8 +153,8 @@ static void adsl_remove(NMAtmManager *self, struct udev_device *udev_device) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self); - const char * iface = udev_device_get_sysname(udev_device); - GSList * iter; + const char *iface = udev_device_get_sysname(udev_device); + GSList *iter; nm_log_dbg(LOGD_PLATFORM, "(%s): removing ATM device", iface); @@ -177,9 +177,9 @@ adsl_remove(NMAtmManager *self, struct udev_device *udev_device) static void start(NMDeviceFactory *factory) { - NMAtmManager * self = NM_ATM_MANAGER(factory); - NMAtmManagerPrivate * priv = NM_ATM_MANAGER_GET_PRIVATE(self); - struct udev_enumerate * enumerate; + NMAtmManager *self = NM_ATM_MANAGER(factory); + NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self); + struct udev_enumerate *enumerate; struct udev_list_entry *devices; enumerate = nm_udev_client_enumerate_new(priv->udev_client); @@ -203,10 +203,10 @@ static void handle_uevent(NMUdevClient *client, struct udev_device *device, gpointer user_data) { NMAtmManager *self = NM_ATM_MANAGER(user_data); - const char * subsys; - const char * ifindex; + const char *subsys; + const char *ifindex; guint64 seqnum; - const char * action; + const char *action; action = udev_device_get_action(device); @@ -245,9 +245,9 @@ nm_atm_manager_init(NMAtmManager *self) static void dispose(GObject *object) { - NMAtmManager * self = NM_ATM_MANAGER(object); + NMAtmManager *self = NM_ATM_MANAGER(object); NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self); - GSList * iter; + GSList *iter; for (iter = priv->devices; iter; iter = iter->next) g_object_weak_unref(G_OBJECT(iter->data), device_destroyed, self); @@ -261,7 +261,7 @@ dispose(GObject *object) static void nm_atm_manager_class_init(NMAtmManagerClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS(klass); object_class->dispose = dispose; diff --git a/src/core/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c index adcf8785..79705c28 100644 --- a/src/core/devices/adsl/nm-device-adsl.c +++ b/src/core/devices/adsl/nm-device-adsl.c @@ -15,13 +15,12 @@ #include <unistd.h> #include <stdlib.h> -#include "nm-ip4-config.h" #include "devices/nm-device-private.h" #include "libnm-platform/nm-platform.h" -#include "ppp/nm-ppp-manager-call.h" -#include "ppp/nm-ppp-status.h" +#include "nm-manager.h" #include "nm-setting-adsl.h" #include "nm-utils.h" +#include "ppp/nm-ppp-mgr.h" #define _NMLOG_DEVICE_TYPE NMDeviceAdsl #include "devices/nm-device-logging.h" @@ -34,15 +33,14 @@ typedef struct { guint carrier_poll_id; int atm_index; - /* PPP */ - NMPPPManager *ppp_manager; + NMPppMgr *ppp_mgr; /* RFC 2684 bridging (PPPoE over ATM) */ - int brfd; - int nas_ifindex; - char *nas_ifname; - guint nas_update_id; - guint nas_update_count; + int brfd; + int nas_ifindex; + char *nas_ifname; + GSource *nas_update_source; + guint nas_update_count; } NMDeviceAdslPrivate; struct _NMDeviceAdsl { @@ -72,7 +70,7 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMSettingAdsl *s_adsl; - const char * protocol; + const char *protocol; if (!NM_DEVICE_CLASS(nm_device_adsl_parent_class) ->check_connection_compatible(device, connection, error)) @@ -93,11 +91,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingAdsl *s_adsl; @@ -126,12 +124,12 @@ complete_connection(NMDevice * device, static gboolean br2684_assign_vcc(NMDeviceAdsl *self, NMSettingAdsl *s_adsl) { - NMDeviceAdslPrivate * priv = NM_DEVICE_ADSL_GET_PRIVATE(self); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); struct sockaddr_atmpvc addr; struct atm_backend_br2684 be; struct atm_qos qos; int errsv, err, bufsize = 8192; - const char * encapsulation; + const char *encapsulation; gboolean is_llc; g_return_val_if_fail(priv->brfd == -1, FALSE); @@ -216,18 +214,18 @@ error: } static void -link_changed_cb(NMPlatform * platform, +link_changed_cb(NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink *info, int change_type_i, - NMDeviceAdsl * self) + NMDeviceAdsl *self) { const NMPlatformSignalChangeType change_type = change_type_i; if (change_type == NM_PLATFORM_SIGNAL_REMOVED) { NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); /* This only gets called for PPPoE connections and "nas" interfaces */ @@ -245,8 +243,8 @@ static gboolean pppoe_vcc_config(NMDeviceAdsl *self) { NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - NMSettingAdsl * s_adsl; + NMDevice *device = NM_DEVICE(self); + NMSettingAdsl *s_adsl; s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL); @@ -271,11 +269,11 @@ pppoe_vcc_config(NMDeviceAdsl *self) } static gboolean -nas_update_cb(gpointer user_data) +nas_update_timeout_cb(gpointer user_data) { - NMDeviceAdsl * self = NM_DEVICE_ADSL(user_data); + NMDeviceAdsl *self = NM_DEVICE_ADSL(user_data); NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); nm_assert(priv->nas_ifname); @@ -284,46 +282,48 @@ nas_update_cb(gpointer user_data) nm_assert(priv->nas_ifindex <= 0); priv->nas_ifindex = nm_platform_link_get_ifindex(nm_device_get_platform(device), priv->nas_ifname); + + if (priv->nas_ifindex <= 0 && priv->nas_update_count <= 10) { + /* Keep waiting for it to appear */ + return G_SOURCE_CONTINUE; + } + + nm_clear_g_source_inst(&priv->nas_update_source); + if (priv->nas_ifindex <= 0) { - if (priv->nas_update_count <= 10) { - /* Keep waiting for it to appear */ - return G_SOURCE_CONTINUE; - } - priv->nas_update_id = 0; _LOGW(LOGD_ADSL, "failed to find br2684 interface %s ifindex after timeout", priv->nas_ifname); nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BR2684_FAILED); - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } - priv->nas_update_id = 0; _LOGD(LOGD_ADSL, "using br2684 iface '%s' index %d", priv->nas_ifname, priv->nas_ifindex); if (!pppoe_vcc_config(self)) { nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_BR2684_FAILED); - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } nm_device_activate_schedule_stage2_device_config(device, TRUE); - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } static gboolean br2684_create_iface(NMDeviceAdsl *self) { - NMDeviceAdslPrivate * priv = NM_DEVICE_ADSL_GET_PRIVATE(self); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); struct atm_newif_br2684 ni; nm_auto_close int fd = -1; - int err, errsv; + int err; + int errsv; guint num = 0; - if (nm_clear_g_source(&priv->nas_update_id)) - nm_assert_not_reached(); + nm_assert(!priv->nas_update_source); fd = socket(PF_ATMPVC, SOCK_DGRAM | SOCK_CLOEXEC, ATM_AAL5); if (fd < 0) { @@ -358,174 +358,187 @@ br2684_create_iface(NMDeviceAdsl *self) nm_strdup_reset(&priv->nas_ifname, ni.ifname); _LOGD(LOGD_ADSL, "waiting for br2684 iface '%s' to appear", priv->nas_ifname); - priv->nas_update_count = 0; - priv->nas_update_id = g_timeout_add(100, nas_update_cb, self); + priv->nas_update_count = 0; + priv->nas_update_source = nm_g_timeout_add_source(100, nas_update_timeout_cb, self); return TRUE; } } -static NMActStageReturn -act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) +/*****************************************************************************/ + +static void +_ppp_mgr_cleanup(NMDeviceAdsl *self) { - NMDeviceAdsl * self = NM_DEVICE_ADSL(device); NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); - NMSettingAdsl * s_adsl; - const char * protocol; - s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL); - - g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE); + nm_clear_pointer(&priv->ppp_mgr, nm_ppp_mgr_destroy); +} - protocol = nm_setting_adsl_get_protocol(s_adsl); - _LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol); +static void +_ppp_mgr_stage3_maybe_ready(NMDeviceAdsl *self) +{ + NMDevice *device = NM_DEVICE(self); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); + int IS_IPv4; - if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) { - /* PPPoA doesn't need anything special */ - return NM_ACT_STAGE_RETURN_SUCCESS; - } + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; + const NMPppMgrIPData *ip_data; - if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) { - /* PPPoE needs RFC2684 bridging before we can do PPP over it */ - if (priv->nas_ifindex <= 0) { - if (priv->nas_update_id == 0) { - if (!br2684_create_iface(self)) { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - } - return NM_ACT_STAGE_RETURN_POSTPONE; - } - return NM_ACT_STAGE_RETURN_SUCCESS; + ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_mgr, addr_family); + if (ip_data->ip_received) + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd); } - _LOGW(LOGD_ADSL, "unhandled ADSL protocol '%s'", protocol); - return NM_ACT_STAGE_RETURN_SUCCESS; + if (nm_ppp_mgr_get_state(priv->ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG) + nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL); } static void -ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data) { - NMDevice *device = NM_DEVICE(user_data); + NMDeviceAdsl *self = NM_DEVICE_ADSL(user_data); + NMDevice *device = NM_DEVICE(self); + NMDeviceState device_state; - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } -} + if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED) + return; -static void -ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data) -{ - NMDevice *device = NM_DEVICE(user_data); + device_state = nm_device_get_state(device); - if (!nm_device_set_ip_ifindex(device, ifindex)) { - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) { + if (device_state <= NM_DEVICE_STATE_ACTIVATED) + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason); + return; } -} -static void -ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) -{ - NMDevice *device = NM_DEVICE(user_data); + if (device_state < NM_DEVICE_STATE_IP_CONFIG) { + if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) { + gs_free char *old_name = NULL; + gs_free_error GError *error = NULL; + + if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) { + _LOGW(LOGD_DEVICE | LOGD_PPP, + "could not take control of link %d: %s", + callback_data->data.ifindex, + error->message); + _ppp_mgr_cleanup(self); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } - /* Ignore PPP IP4 events that come in after initial configuration */ - if (nm_device_activate_ip4_state_in_conf(device)) - nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config)); + if (old_name) + nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_ADSL); + + nm_device_activate_schedule_stage2_device_config(device, FALSE); + } + return; + } + + _ppp_mgr_stage3_maybe_ready(self); } +/*****************************************************************************/ + static NMActStageReturn -act_stage3_ip4_config_start(NMDevice * device, - NMIP4Config ** out_config, - NMDeviceStateReason *out_failure_reason) +act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceAdsl * self = NM_DEVICE_ADSL(device); + NMDeviceAdsl *self = NM_DEVICE_ADSL(device); NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); - NMSettingAdsl * s_adsl; - NMActRequest * req; - GError * err = NULL; - const char * ppp_iface; - - req = nm_device_get_act_request(device); - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); + if (!priv->ppp_mgr) { + gs_free_error GError *error = NULL; + NMSettingAdsl *s_adsl; + const char *protocol; + NMActRequest *req; + const char *ppp_iface; + + req = nm_device_get_act_request(device); + g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); + + s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL); + g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE); + + protocol = nm_setting_adsl_get_protocol(s_adsl); + + _LOGD(LOGD_ADSL, "using ADSL protocol '%s'", protocol); + + if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) { + /* PPPoA doesn't need anything special */ + } else if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) { + /* PPPoE needs RFC2684 bridging before we can do PPP over it */ + if (priv->nas_ifindex <= 0) { + if (!priv->nas_update_source) { + if (!br2684_create_iface(self)) { + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_BR2684_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + } + return NM_ACT_STAGE_RETURN_POSTPONE; + } + } else + nm_assert(nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM)); + + /* PPPoE uses the NAS interface, not the ATM interface */ + if (nm_streq0(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) { + nm_assert(priv->nas_ifname); + ppp_iface = priv->nas_ifname; + _LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname); + } else { + ppp_iface = nm_device_get_iface(device); + _LOGD(LOGD_ADSL, "starting PPPoA"); + } - s_adsl = nm_device_get_applied_setting(device, NM_TYPE_SETTING_ADSL); + priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){ + .netns = nm_device_get_netns(device), + .parent_iface = ppp_iface, + .callback = _ppp_mgr_callback, + .user_data = self, + .act_req = req, + .ppp_username = nm_setting_adsl_get_username(s_adsl), + .timeout_secs = 30, + .baud_override = 0, + }), + &error); + if (!priv->ppp_mgr) { + _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message); + *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } - g_return_val_if_fail(s_adsl, NM_ACT_STAGE_RETURN_FAILURE); + return NM_ACT_STAGE_RETURN_POSTPONE; + } - /* PPPoE uses the NAS interface, not the ATM interface */ - if (nm_streq0(nm_setting_adsl_get_protocol(s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE)) { - nm_assert(priv->nas_ifname); - ppp_iface = priv->nas_ifname; + if (nm_ppp_mgr_get_state(priv->ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX) + return NM_ACT_STAGE_RETURN_POSTPONE; - _LOGD(LOGD_ADSL, "starting PPPoE on br2684 interface %s", priv->nas_ifname); - } else { - ppp_iface = nm_device_get_iface(device); - _LOGD(LOGD_ADSL, "starting PPPoA"); - } + return NM_ACT_STAGE_RETURN_SUCCESS; +} - priv->ppp_manager = nm_ppp_manager_create(ppp_iface, &err); +static void +act_stage3_ip_config(NMDevice *device, int addr_family) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL(device); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); + NMPppMgrState ppp_state; - if (priv->ppp_manager) { - nm_ppp_manager_set_route_parameters(priv->ppp_manager, - nm_device_get_route_table(device, AF_INET), - nm_device_get_route_metric(device, AF_INET), - nm_device_get_route_table(device, AF_INET6), - nm_device_get_route_metric(device, AF_INET6)); + if (!priv->ppp_mgr) { + nm_assert_not_reached(); + return; } - if (!priv->ppp_manager - || !nm_ppp_manager_start(priv->ppp_manager, - req, - nm_setting_adsl_get_username(s_adsl), - 30, - 0, - &err)) { - _LOGW(LOGD_ADSL, "PPP failed to start: %s", err->message); - g_error_free(err); + ppp_state = nm_ppp_mgr_get_state(priv->ppp_mgr); - g_clear_object(&priv->ppp_manager); + nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG)); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; + if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) { + nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL); + return; } - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, - G_CALLBACK(ppp_state_changed), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK(ppp_ifindex_set), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, - G_CALLBACK(ppp_ip4_config), - self); - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) -{ - if (addr_family == AF_INET) - return act_stage3_ip4_config_start(device, (NMIP4Config **) out_config, out_failure_reason); - - return NM_DEVICE_CLASS(nm_device_adsl_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + _ppp_mgr_stage3_maybe_ready(self); } static void @@ -533,23 +546,15 @@ adsl_cleanup(NMDeviceAdsl *self) { NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); - if (priv->ppp_manager) { - g_signal_handlers_disconnect_by_func(priv->ppp_manager, - G_CALLBACK(ppp_state_changed), - self); - g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_ip4_config), self); - nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL); - g_clear_object(&priv->ppp_manager); - } + _ppp_mgr_cleanup(self); g_signal_handlers_disconnect_by_func(nm_device_get_platform(NM_DEVICE(self)), G_CALLBACK(link_changed_cb), self); - nm_close(priv->brfd); - priv->brfd = -1; + nm_clear_fd(&priv->brfd); - nm_clear_g_source(&priv->nas_update_id); + nm_clear_g_source_inst(&priv->nas_update_source); /* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet, * so it gets leaked. It does get destroyed when it's no longer in use, @@ -572,7 +577,7 @@ carrier_update_cb(gpointer user_data) { NMDeviceAdsl *self = NM_DEVICE_ADSL(user_data); int carrier; - char * path; + char *path; path = g_strdup_printf("/sys/class/atm/%s/carrier", NM_ASSERT_VALID_PATH_COMPONENT(nm_device_get_iface(NM_DEVICE(self)))); @@ -627,7 +632,7 @@ nm_device_adsl_init(NMDeviceAdsl *self) static void constructed(GObject *object) { - NMDeviceAdsl * self = NM_DEVICE_ADSL(object); + NMDeviceAdsl *self = NM_DEVICE_ADSL(object); NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); G_OBJECT_CLASS(nm_device_adsl_parent_class)->constructed(object); @@ -681,9 +686,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_adsl = { static void nm_device_adsl_class_init(NMDeviceAdslClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructed = constructed; object_class->dispose = dispose; @@ -699,9 +704,9 @@ nm_device_adsl_class_init(NMDeviceAdslClass *klass) device_class->check_connection_compatible = check_connection_compatible; device_class->complete_connection = complete_connection; - device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->deactivate = deactivate; + device_class->act_stage2_config = act_stage2_config; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->deactivate = deactivate; obj_properties[PROP_ATM_INDEX] = g_param_spec_int(NM_DEVICE_ADSL_ATM_INDEX, diff --git a/src/core/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index 36e442ad..05f85297 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -38,7 +38,7 @@ #define _NM_BT_CAPABILITY_SUPPORTED (NM_BT_CAPABILITY_NAP | _NM_BT_CAPABILITY_SUPPORTED_DUN) typedef struct { - const char * bdaddr; + const char *bdaddr; CList lst_head; NMBluetoothCapabilities bt_type : 8; char bdaddr_data[]; @@ -46,24 +46,24 @@ typedef struct { typedef struct { NMSettingsConnection *sett_conn; - ConnDataHead * cdata_hd; + ConnDataHead *cdata_hd; CList lst; } ConnDataElem; typedef struct { - GCancellable * ext_cancellable; - GCancellable * int_cancellable; + GCancellable *ext_cancellable; + GCancellable *int_cancellable; NMBtVTableRegisterCallback callback; gpointer callback_user_data; gulong ext_cancelled_id; } NetworkServerRegisterReqData; typedef struct { - GCancellable * ext_cancellable; - GCancellable * int_cancellable; + GCancellable *ext_cancellable; + GCancellable *int_cancellable; NMBluezManagerConnectCb callback; gpointer callback_user_data; - char * device_name; + char *device_name; gulong ext_cancelled_id; guint timeout_id; guint timeout_wait_connect_id; @@ -97,16 +97,16 @@ typedef struct { struct { CList lst; - char * adapter_address; - NMDevice * device_br; + char *adapter_address; + NMDevice *device_br; NetworkServerRegisterReqData *r_req_data; } x_network_server; struct { NMSettingsConnection *panu_connection; - NMDeviceBt * device_bt; + NMDeviceBt *device_bt; DeviceConnectReqData *c_req_data; - NMBluez5DunContext * connect_dun_context; + NMBluez5DunContext *connect_dun_context; gulong device_bt_signal_id; } x_device; @@ -142,7 +142,7 @@ typedef struct { } BzDBusObj; typedef struct { - NMManager * manager; + NMManager *manager; NMSettings *settings; GDBusConnection *dbus_connection; @@ -194,7 +194,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES(NM_DEVICE_FACTORY_DECLARE_LINK_TYPES( NM_LINK_TYPE_BNEP) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_BLUETOOTH_SETTING_NAME)) G_MODULE_EXPORT NMDeviceFactory * - nm_device_factory_create(GError **error) +nm_device_factory_create(GError **error) { return g_object_new(NM_TYPE_BLUEZ_MANAGER, NULL); } @@ -214,8 +214,8 @@ convert_uuids_to_capabilities(const char *const *strv) if (strv) { for (; strv[0]; strv++) { gs_free char *s_part1 = NULL; - const char * str = strv[0]; - const char * s; + const char *str = strv[0]; + const char *s; s = strchr(str, '-'); if (!s) @@ -245,8 +245,8 @@ static void _connect_disconnect(NMBluezManager *self, BzDBusObj *bzobj, cons static gboolean _bzobjs_network_server_is_usable(const BzDBusObj *bzobj, gboolean require_powered); static gboolean _bzobjs_is_dead(const BzDBusObj *bzobj); static gboolean _bzobjs_device_is_usable(const BzDBusObj *bzobj, - BzDBusObj ** out_adapter_bzobj, - gboolean * out_create_panu_connection); + BzDBusObj **out_adapter_bzobj, + gboolean *out_create_panu_connection); static gboolean _bzobjs_adapter_is_usable_for_device(const BzDBusObj *bzobj); static ConnDataHead * _conn_track_find_head(NMBluezManager *self, NMBluetoothCapabilities bt_type, const char *bdaddr); @@ -293,9 +293,9 @@ _network_server_register_req_data_complete(NetworkServerRegisterReqData *r_req_d static void _device_connect_req_data_complete(DeviceConnectReqData *c_req_data, - NMBluezManager * self, - const char * device_name, - GError * error) + NMBluezManager *self, + const char *device_name, + GError *error) { nm_assert((!!device_name) != (!!error)); @@ -371,7 +371,7 @@ _bz_dbus_obj_free(BzDBusObj *bzobj) static const char * _bzobj_to_string(const BzDBusObj *bzobj, char *buf, gsize len) { - char * buf0 = buf; + char *buf0 = buf; const char *prefix = ""; gboolean device_is_usable; gboolean create_panu_connection = FALSE; @@ -591,7 +591,7 @@ static BzDBusObj * _bzobjs_add(NMBluezManager *self, const char *object_path) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - BzDBusObj * bzobj; + BzDBusObj *bzobj; bzobj = _bz_dbus_obj_new(self, object_path); if (!g_hash_table_add(priv->bzobjs, bzobj)) @@ -642,14 +642,14 @@ _bzobjs_adapter_is_usable_for_device(const BzDBusObj *bzobj) static gboolean _bzobjs_device_is_usable(const BzDBusObj *bzobj, - BzDBusObj ** out_adapter_bzobj, - gboolean * out_create_panu_connection) + BzDBusObj **out_adapter_bzobj, + gboolean *out_create_panu_connection) { - NMBluezManager * self; + NMBluezManager *self; NMBluezManagerPrivate *priv; gboolean usable_dun = FALSE; gboolean usable_nap = FALSE; - BzDBusObj * bzobj_adapter; + BzDBusObj *bzobj_adapter; gboolean create_panu_connection = FALSE; if (!bzobj->d_has_device_iface @@ -805,14 +805,14 @@ _conn_track_find_elem(NMBluezManager *self, NMSettingsConnection *sett_conn) } static gboolean -_conn_track_is_relevant_connection(NMConnection * connection, +_conn_track_is_relevant_connection(NMConnection *connection, NMBluetoothCapabilities *out_bt_type, - const char ** out_bdaddr) + const char **out_bdaddr) { - NMSettingBluetooth * s_bt; + NMSettingBluetooth *s_bt; NMBluetoothCapabilities bt_type; - const char * bdaddr; - const char * b_type; + const char *bdaddr; + const char *b_type; s_bt = nm_connection_get_setting_bluetooth(connection); if (!s_bt) @@ -840,9 +840,9 @@ _conn_track_is_relevant_connection(NMConnection * connection, } static gboolean -_conn_track_is_relevant_sett_conn(NMSettingsConnection * sett_conn, +_conn_track_is_relevant_sett_conn(NMSettingsConnection *sett_conn, NMBluetoothCapabilities *out_bt_type, - const char ** out_bdaddr) + const char **out_bdaddr) { NMConnection *connection; @@ -854,25 +854,25 @@ _conn_track_is_relevant_sett_conn(NMSettingsConnection * sett_conn, } static gboolean -_conn_track_is_relevant_for_sett_conn(NMSettingsConnection * sett_conn, +_conn_track_is_relevant_for_sett_conn(NMSettingsConnection *sett_conn, NMBluetoothCapabilities bt_type, - const char * bdaddr) + const char *bdaddr) { NMBluetoothCapabilities x_bt_type; - const char * x_bdaddr; + const char *x_bdaddr; return bdaddr && _conn_track_is_relevant_sett_conn(sett_conn, &x_bt_type, &x_bdaddr) && x_bt_type == bt_type && nm_streq(x_bdaddr, bdaddr); } static void -_conn_track_schedule_notify(NMBluezManager * self, +_conn_track_schedule_notify(NMBluezManager *self, NMBluetoothCapabilities bt_type, - const char * bdaddr) + const char *bdaddr) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); GHashTableIter iter; - BzDBusObj * bzobj; + BzDBusObj *bzobj; g_hash_table_iter_init(&iter, priv->bzobjs); while (g_hash_table_iter_next(&iter, (gpointer *) &bzobj, NULL)) { @@ -885,19 +885,19 @@ _conn_track_schedule_notify(NMBluezManager * self, } static void -_conn_track_update(NMBluezManager * self, +_conn_track_update(NMBluezManager *self, NMSettingsConnection *sett_conn, gboolean track, - gboolean * out_changed, - gboolean * out_changed_usable, - ConnDataElem ** out_conn_data_elem) -{ - NMBluezManagerPrivate * priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - ConnDataHead * cdata_hd; - ConnDataElem * cdata_el; - ConnDataElem * cdata_el_remove = NULL; + gboolean *out_changed, + gboolean *out_changed_usable, + ConnDataElem **out_conn_data_elem) +{ + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); + ConnDataHead *cdata_hd; + ConnDataElem *cdata_el; + ConnDataElem *cdata_el_remove = NULL; NMBluetoothCapabilities bt_type; - const char * bdaddr; + const char *bdaddr; gboolean changed = FALSE; gboolean changed_usable = FALSE; char sbuf_cap[100]; @@ -946,7 +946,7 @@ _conn_track_update(NMBluezManager * self, out_remove: if (cdata_el_remove) { GHashTableIter iter; - BzDBusObj * bzobj; + BzDBusObj *bzobj; _LOGT("connection: untrack for %s, %s: %s (%s)", nm_bluetooth_capability_to_string(cdata_el_remove->cdata_hd->bt_type, @@ -989,10 +989,10 @@ cp_connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, NMBlu } static void -cp_connection_updated(NMSettings * settings, +cp_connection_updated(NMSettings *settings, NMSettingsConnection *sett_conn, guint update_reason_u, - NMBluezManager * self) + NMBluezManager *self) { _conn_track_update(self, sett_conn, TRUE, NULL, NULL, NULL); } @@ -1032,8 +1032,8 @@ _network_server_find_has_device(NMBluezManagerPrivate *priv, NMDevice *device) static BzDBusObj * _network_server_find_available(NMBluezManagerPrivate *priv, - const char * addr, - NMDevice * device_accept_busy) + const char *addr, + NMDevice *device_accept_busy) { BzDBusObj *bzobj; @@ -1052,10 +1052,10 @@ _network_server_find_available(NMBluezManagerPrivate *priv, static gboolean _network_server_vt_is_available(const NMBtVTableNetworkServer *vtable, - const char * addr, - NMDevice * device_accept_busy) + const char *addr, + NMDevice *device_accept_busy) { - NMBluezManager * self = _network_server_get_bluez_manager(vtable); + NMBluezManager *self = _network_server_get_bluez_manager(vtable); NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); return !!_network_server_find_available(priv, addr, device_accept_busy); @@ -1064,9 +1064,9 @@ _network_server_vt_is_available(const NMBtVTableNetworkServer *vtable, static void _network_server_register_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - gs_unref_variant GVariant *ret = NULL; - gs_free_error GError *error = NULL; - BzDBusObj * bzobj; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + BzDBusObj *bzobj; ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source_object), res, &error); if (!ret && nm_utils_error_is_cancelled(error)) @@ -1092,18 +1092,18 @@ _network_server_register_cancelled_cb(GCancellable *cancellable, BzDBusObj *bzob static gboolean _network_server_vt_register_bridge(const NMBtVTableNetworkServer *vtable, - const char * addr, - NMDevice * device, - GCancellable * cancellable, + const char *addr, + NMDevice *device, + GCancellable *cancellable, NMBtVTableRegisterCallback callback, gpointer callback_user_data, - GError ** error) + GError **error) { - NMBluezManager * self = _network_server_get_bluez_manager(vtable); - NMBluezManagerPrivate * priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); + NMBluezManager *self = _network_server_get_bluez_manager(vtable); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); NetworkServerRegisterReqData *r_req_data; - BzDBusObj * bzobj; - const char * ifname; + BzDBusObj *bzobj; + const char *ifname; g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); g_return_val_if_fail(G_IS_CANCELLABLE(cancellable), FALSE); @@ -1174,8 +1174,8 @@ _network_server_vt_register_bridge(const NMBtVTableNetworkServer *vtable, static void _network_server_unregister_bridge_complete_on_idle_cb(gpointer user_data, GCancellable *cancellable) { - gs_free_error GError * error = NULL; - gs_free char * reason = NULL; + gs_free_error GError *error = NULL; + gs_free char *reason = NULL; NetworkServerRegisterReqData *r_req_data; nm_utils_user_data_unpack(user_data, &r_req_data, &reason); @@ -1190,9 +1190,9 @@ _network_server_unregister_bridge_complete_on_idle_cb(gpointer user_data, GCance static void _network_server_unregister_bridge(NMBluezManager *self, BzDBusObj *bzobj, const char *reason) { - NMBluezManagerPrivate * priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); _nm_unused gs_unref_object NMDevice *device = NULL; - NetworkServerRegisterReqData * r_req_data; + NetworkServerRegisterReqData *r_req_data; nm_assert(NM_IS_DEVICE(bzobj->x_network_server.device_br)); @@ -1242,9 +1242,9 @@ _network_server_unregister_bridge(NMBluezManager *self, BzDBusObj *bzobj, const static gboolean _network_server_vt_unregister_bridge(const NMBtVTableNetworkServer *vtable, NMDevice *device) { - NMBluezManager * self = _network_server_get_bluez_manager(vtable); + NMBluezManager *self = _network_server_get_bluez_manager(vtable); NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - BzDBusObj * bzobj; + BzDBusObj *bzobj; g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); @@ -1258,7 +1258,7 @@ _network_server_vt_unregister_bridge(const NMBtVTableNetworkServer *vtable, NMDe static void _network_server_process_change(BzDBusObj *bzobj, gboolean *out_emit_device_availability_changed) { - NMBluezManager * self = bzobj->self; + NMBluezManager *self = bzobj->self; NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); gboolean network_server_is_usable; gboolean emit_device_availability_changed = FALSE; @@ -1303,13 +1303,13 @@ _network_server_process_change(BzDBusObj *bzobj, gboolean *out_emit_device_avail static void _conn_create_panu_connection(NMBluezManager *self, BzDBusObj *bzobj) { - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); gs_unref_object NMConnection *connection = NULL; - NMSettingsConnection * added; - NMSetting * setting; - gs_free char * id = NULL; + NMSettingsConnection *added; + NMSetting *setting; + gs_free char *id = NULL; char uuid[37]; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; nm_uuid_generate_random_str_arr(uuid); id = g_strdup_printf(_("%s Network"), bzobj->d_device.name); @@ -1398,7 +1398,7 @@ _device_state_changed_cb(NMDevice *device, static void _device_process_change(BzDBusObj *bzobj) { - NMBluezManager *self = bzobj->self; + NMBluezManager *self = bzobj->self; gs_unref_object NMDeviceBt *device_added = NULL; gs_unref_object NMDeviceBt *device_deleted = NULL; gboolean device_is_usable; @@ -1513,7 +1513,7 @@ static void _process_change_idle_all(NMBluezManager *self, gboolean *out_emit_device_availability_changed) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - BzDBusObj * bzobj; + BzDBusObj *bzobj; while ( (bzobj = @@ -1537,7 +1537,7 @@ _process_change_idle_all(NMBluezManager *self, gboolean *out_emit_device_availab static gboolean _process_change_idle_cb(gpointer user_data) { - NMBluezManager * self = user_data; + NMBluezManager *self = user_data; NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); gboolean emit_device_availability_changed = FALSE; @@ -1622,7 +1622,7 @@ _dbus_process_changes(NMBluezManager *self, BzDBusObj *bzobj, const char *log_re if (recheck_devices_for_adapter) { GHashTableIter iter; - BzDBusObj * bzobj2; + BzDBusObj *bzobj2; /* we got a change to the availability of an adapter. We might need to recheck * all devices that use this adapter... */ @@ -1651,17 +1651,17 @@ _dbus_process_changes(NMBluezManager *self, BzDBusObj *bzobj, const char *log_re NM_BLUEZ5_NETWORK_SERVER_INTERFACE) static gboolean -_dbus_handle_properties_changed(NMBluezManager * self, - const char * object_path, - const char * interface_name, - GVariant * changed_properties, +_dbus_handle_properties_changed(NMBluezManager *self, + const char *object_path, + const char *interface_name, + GVariant *changed_properties, const char *const *invalidated_properties, - BzDBusObj ** inout_bzobj) + BzDBusObj **inout_bzobj) { - BzDBusObj * bzobj = NULL; + BzDBusObj *bzobj = NULL; gboolean changed = FALSE; - const char * property_name; - GVariant * property_value; + const char *property_name; + GVariant *property_value; GVariantIter iter_prop; gsize i; @@ -1933,14 +1933,14 @@ _dbus_handle_properties_changed(NMBluezManager * self, static void _dbus_handle_interface_added(NMBluezManager *self, - const char * object_path, - GVariant * ifaces, + const char *object_path, + GVariant *ifaces, gboolean initial_get_managed_objects) { - BzDBusObj * bzobj = NULL; + BzDBusObj *bzobj = NULL; gboolean changed = FALSE; - const char * interface_name; - GVariant * changed_properties; + const char *interface_name; + GVariant *changed_properties; GVariantIter iter_ifaces; nm_assert(g_variant_is_of_type(ifaces, G_VARIANT_TYPE("a{sa{sv}}"))); @@ -1966,9 +1966,9 @@ _dbus_handle_interface_added(NMBluezManager *self, } static gboolean -_dbus_handle_interface_removed(NMBluezManager * self, - const char * object_path, - BzDBusObj ** inout_bzobj, +_dbus_handle_interface_removed(NMBluezManager *self, + const char *object_path, + BzDBusObj **inout_bzobj, const char *const *removed_interfaces) { gboolean changed = FALSE; @@ -2056,16 +2056,16 @@ _dbus_handle_interface_removed(NMBluezManager * self, static void _dbus_managed_objects_changed_cb(GDBusConnection *connection, - const char * sender_name, - const char * arg_object_path, - const char * interface_name, - const char * signal_name, - GVariant * parameters, + const char *sender_name, + const char *arg_object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, gpointer user_data) { - NMBluezManager * self = user_data; + NMBluezManager *self = user_data; NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - BzDBusObj * bzobj = NULL; + BzDBusObj *bzobj = NULL; gboolean changed; nm_assert(nm_streq0(interface_name, DBUS_INTERFACE_OBJECT_MANAGER)); @@ -2077,7 +2077,7 @@ _dbus_managed_objects_changed_cb(GDBusConnection *connection, if (nm_streq(signal_name, "InterfacesAdded")) { gs_unref_variant GVariant *interfaces_and_properties = NULL; - const char * object_path; + const char *object_path; if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(oa{sa{sv}})"))) return; @@ -2090,7 +2090,7 @@ _dbus_managed_objects_changed_cb(GDBusConnection *connection, if (nm_streq(signal_name, "InterfacesRemoved")) { gs_free const char **interfaces = NULL; - const char * object_path; + const char *object_path; if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(oas)"))) return; @@ -2106,19 +2106,19 @@ _dbus_managed_objects_changed_cb(GDBusConnection *connection, static void _dbus_properties_changed_cb(GDBusConnection *connection, - const char * sender_name, - const char * object_path, - const char * signal_interface_name, - const char * signal_name, - GVariant * parameters, + const char *sender_name, + const char *object_path, + const char *signal_interface_name, + const char *signal_name, + GVariant *parameters, gpointer user_data) { - NMBluezManager * self = user_data; - NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - const char * interface_name; + NMBluezManager *self = user_data; + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); + const char *interface_name; gs_unref_variant GVariant *changed_properties = NULL; - gs_free const char ** invalidated_properties = NULL; - BzDBusObj * bzobj = NULL; + gs_free const char **invalidated_properties = NULL; + BzDBusObj *bzobj = NULL; if (priv->get_managed_objects_cancellable) { /* we still wait for the initial GetManagedObjects(). Ignore the event. */ @@ -2146,11 +2146,11 @@ _dbus_properties_changed_cb(GDBusConnection *connection, static void _dbus_get_managed_objects_cb(GVariant *result, GError *error, gpointer user_data) { - NMBluezManager * self; + NMBluezManager *self; NMBluezManagerPrivate *priv; GVariantIter iter; - const char * object_path; - GVariant * ifaces; + const char *object_path; + GVariant *ifaces; if (!result && nm_utils_error_is_cancelled(error)) return; @@ -2184,7 +2184,7 @@ _cleanup_for_name_owner(NMBluezManager *self) NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); gboolean emit_device_availability_changed = FALSE; GHashTableIter iter; - BzDBusObj * bzobj; + BzDBusObj *bzobj; gboolean first = TRUE; nm_clear_g_cancellable(&priv->get_managed_objects_cancellable); @@ -2217,7 +2217,7 @@ static void name_owner_changed(NMBluezManager *self, const char *owner) { _nm_unused gs_unref_object NMBluezManager *self_keep_alive = g_object_ref(self); - NMBluezManagerPrivate * priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); owner = nm_str_not_empty(owner); @@ -2270,15 +2270,15 @@ name_owner_changed(NMBluezManager *self, const char *owner) static void name_owner_changed_cb(GDBusConnection *connection, - const char * sender_name, - const char * object_path, - const char * interface_name, - const char * signal_name, - GVariant * parameters, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, gpointer user_data) { NMBluezManager *self = user_data; - const char * new_owner; + const char *new_owner; if (!g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) return; @@ -2321,8 +2321,8 @@ _cleanup_all(NMBluezManager *self) static void start(NMDeviceFactory *factory) { - NMBluezManager * self; - NMBluezManagerPrivate * priv; + NMBluezManager *self; + NMBluezManagerPrivate *priv; NMSettingsConnection *const *sett_conns; guint n_sett_conns; guint i; @@ -2378,12 +2378,12 @@ start(NMDeviceFactory *factory) /*****************************************************************************/ static void -_connect_returned(NMBluezManager * self, - BzDBusObj * bzobj, +_connect_returned(NMBluezManager *self, + BzDBusObj *bzobj, NMBluetoothCapabilities bt_type, - const char * device_name, - NMBluez5DunContext * dun_context, - GError * error) + const char *device_name, + NMBluez5DunContext *dun_context, + GError *error) { char sbuf_cap[100]; @@ -2449,8 +2449,8 @@ _connect_dun_notify_tty_hangup_cb(NMBluez5DunContext *context, gpointer user_dat static void _connect_dun_step2_cb(NMBluez5DunContext *context, - const char * rfcomm_dev, - GError * error, + const char *rfcomm_dev, + GError *error, gpointer user_data) { BzDBusObj *bzobj; @@ -2491,10 +2491,10 @@ _connect_dun_step2_cb(NMBluez5DunContext *context, static void _connect_dun_step1_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - gs_unref_variant GVariant *ret = NULL; - gs_free_error GError *error = NULL; - BzDBusObj * bzobj_adapter; - BzDBusObj * bzobj; + gs_unref_variant GVariant *ret = NULL; + gs_free_error GError *error = NULL; + BzDBusObj *bzobj_adapter; + BzDBusObj *bzobj; ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source_object), res, &error); @@ -2537,9 +2537,9 @@ static void _connect_nap_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { gs_unref_variant GVariant *ret = NULL; - const char * network_iface_name = NULL; - gs_free_error GError *error = NULL; - BzDBusObj * bzobj; + const char *network_iface_name = NULL; + gs_free_error GError *error = NULL; + BzDBusObj *bzobj; ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source_object), res, &error); @@ -2584,7 +2584,7 @@ static void _connect_disconnect(NMBluezManager *self, BzDBusObj *bzobj, const char *reason) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - DeviceConnectReqData * c_req_data; + DeviceConnectReqData *c_req_data; char sbuf_cap[100]; gboolean bt_type; @@ -2655,19 +2655,19 @@ _connect_disconnect(NMBluezManager *self, BzDBusObj *bzobj, const char *reason) } gboolean -nm_bluez_manager_connect(NMBluezManager * self, - const char * object_path, +nm_bluez_manager_connect(NMBluezManager *self, + const char *object_path, NMBluetoothCapabilities connection_bt_type, int timeout_msec, - GCancellable * cancellable, + GCancellable *cancellable, NMBluezManagerConnectCb callback, gpointer callback_user_data, - GError ** error) + GError **error) { gs_unref_object GCancellable *int_cancellable = NULL; - DeviceConnectReqData * c_req_data; - NMBluezManagerPrivate * priv; - BzDBusObj * bzobj; + DeviceConnectReqData *c_req_data; + NMBluezManagerPrivate *priv; + BzDBusObj *bzobj; char sbuf_cap[100]; g_return_val_if_fail(NM_IS_BLUEZ_MANAGER(self), FALSE); @@ -2781,11 +2781,11 @@ nm_bluez_manager_disconnect(NMBluezManager *self, const char *object_path) /*****************************************************************************/ static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { *out_ignore = TRUE; g_return_val_if_fail(plink->type == NM_LINK_TYPE_BNEP, NULL); @@ -2845,7 +2845,7 @@ nm_bluez_manager_init(NMBluezManager *self) static void dispose(GObject *object) { - NMBluezManager * self = NM_BLUEZ_MANAGER(object); + NMBluezManager *self = NM_BLUEZ_MANAGER(object); NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); /* FIXME(shutdown): we need a nm_device_factory_stop() hook to first unregister all @@ -2877,7 +2877,7 @@ dispose(GObject *object) static void nm_bluez_manager_class_init(NMBluezManagerClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS(klass); object_class->dispose = dispose; diff --git a/src/core/devices/bluetooth/nm-bluez-manager.h b/src/core/devices/bluetooth/nm-bluez-manager.h index 04bfea7d..299f5c3b 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.h +++ b/src/core/devices/bluetooth/nm-bluez-manager.h @@ -24,18 +24,18 @@ GType nm_bluez_manager_get_type(void); typedef void (*NMBluezManagerConnectCb)( NMBluezManager *self, gboolean is_completed /* or else is early notification with DUN path */, - const char * device_name, - GError * error, + const char *device_name, + GError *error, gpointer user_data); -gboolean nm_bluez_manager_connect(NMBluezManager * self, - const char * object_path, +gboolean nm_bluez_manager_connect(NMBluezManager *self, + const char *object_path, NMBluetoothCapabilities connection_bt_type, int timeout_msec, - GCancellable * cancellable, + GCancellable *cancellable, NMBluezManagerConnectCb callback, gpointer callback_user_data, - GError ** error); + GError **error); void nm_bluez_manager_disconnect(NMBluezManager *self, const char *object_path); diff --git a/src/core/devices/bluetooth/nm-bluez5-dun.c b/src/core/devices/bluetooth/nm-bluez5-dun.c index 7efbfaf4..426bab0c 100644 --- a/src/core/devices/bluetooth/nm-bluez5-dun.c +++ b/src/core/devices/bluetooth/nm-bluez5-dun.c @@ -23,7 +23,7 @@ /*****************************************************************************/ typedef struct { - GCancellable * cancellable; + GCancellable *cancellable; NMBluez5DunConnectCb callback; gpointer callback_user_data; @@ -265,10 +265,10 @@ _connect_create_rfcomm(NMBluez5DunContext *context) static gboolean _connect_socket_connect_cb(int fd, GIOCondition condition, gpointer user_data) { - NMBluez5DunContext *context = user_data; - gs_free_error GError *error = NULL; - int errsv = 0; - socklen_t slen = sizeof(errsv); + NMBluez5DunContext *context = user_data; + gs_free_error GError *error = NULL; + int errsv = 0; + socklen_t slen = sizeof(errsv); int r; nm_clear_g_source_inst(&context->cdat->source); @@ -415,7 +415,7 @@ _connect_sdp_search_cb(uint8_t type, uint16_t status, uint8_t *rsp, size_t size, do { sdp_record_t *rec; int recsize = 0; - sdp_list_t * protos; + sdp_list_t *protos; rec = sdp_extract_pdu(rsp, bytesleft, &recsize); if (!rec) @@ -454,8 +454,8 @@ _connect_sdp_search_cb(uint8_t type, uint16_t status, uint8_t *rsp, size_t size, static gboolean _connect_sdp_search_io_cb(int fd, GIOCondition condition, gpointer user_data) { - NMBluez5DunContext *context = user_data; - gs_free_error GError *error = NULL; + NMBluez5DunContext *context = user_data; + gs_free_error GError *error = NULL; int errsv; if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { @@ -505,8 +505,8 @@ _connect_sdp_search_io_cb(int fd, GIOCondition condition, gpointer user_data) static gboolean _connect_sdp_session_start_on_idle_cb(gpointer user_data) { - NMBluez5DunContext *context = user_data; - gs_free_error GError *error = NULL; + NMBluez5DunContext *context = user_data; + gs_free_error GError *error = NULL; nm_clear_g_source_inst(&context->cdat->source); @@ -521,15 +521,15 @@ _connect_sdp_session_start_on_idle_cb(gpointer user_data) static gboolean _connect_sdp_io_cb(int fd, GIOCondition condition, gpointer user_data) { - NMBluez5DunContext *context = user_data; - sdp_list_t * search; - sdp_list_t * attrs; - uuid_t svclass; - uint16_t attr; - int errsv; - int fd_err = 0; - int r; - socklen_t len = sizeof(fd_err); + NMBluez5DunContext *context = user_data; + sdp_list_t *search; + sdp_list_t *attrs; + uuid_t svclass; + uint16_t attr; + int errsv; + int fd_err = 0; + int r; + socklen_t len = sizeof(fd_err); gs_free_error GError *error = NULL; nm_clear_g_source_inst(&context->cdat->source); @@ -657,17 +657,17 @@ _connect_sdp_session_start(NMBluez5DunContext *context, GError **error) /*****************************************************************************/ gboolean -nm_bluez5_dun_connect(const char * adapter, - const char * remote, - GCancellable * cancellable, +nm_bluez5_dun_connect(const char *adapter, + const char *remote, + GCancellable *cancellable, NMBluez5DunConnectCb callback, gpointer callback_user_data, NMBluez5DunNotifyTtyHangupCb notify_tty_hangup_cb, gpointer notify_tty_hangup_user_data, - GError ** error) + GError **error) { nm_auto_free_context NMBluez5DunContext *context = NULL; - ConnectData * cdat; + ConnectData *cdat; gsize src_l; gsize dst_l; diff --git a/src/core/devices/bluetooth/nm-bluez5-dun.h b/src/core/devices/bluetooth/nm-bluez5-dun.h index 020d4119..72ca1380 100644 --- a/src/core/devices/bluetooth/nm-bluez5-dun.h +++ b/src/core/devices/bluetooth/nm-bluez5-dun.h @@ -11,20 +11,20 @@ typedef struct _NMBluez5DunContext NMBluez5DunContext; #if WITH_BLUEZ5_DUN typedef void (*NMBluez5DunConnectCb)(NMBluez5DunContext *context, - const char * rfcomm_dev, - GError * error, + const char *rfcomm_dev, + GError *error, gpointer user_data); typedef void (*NMBluez5DunNotifyTtyHangupCb)(NMBluez5DunContext *context, gpointer user_data); -gboolean nm_bluez5_dun_connect(const char * adapter, - const char * remote, - GCancellable * cancellable, +gboolean nm_bluez5_dun_connect(const char *adapter, + const char *remote, + GCancellable *cancellable, NMBluez5DunConnectCb callback, gpointer callback_user_data, NMBluez5DunNotifyTtyHangupCb notify_tty_hangup_cb, gpointer notify_tty_hangup_user_data, - GError ** error); + GError **error); void nm_bluez5_dun_disconnect(NMBluez5DunContext *context); diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c index 3dbfbbe0..39b5c4ec 100644 --- a/src/core/devices/bluetooth/nm-device-bt.c +++ b/src/core/devices/bluetooth/nm-device-bt.c @@ -26,7 +26,6 @@ #include "settings/nm-settings-connection.h" #include "nm-utils.h" #include "nm-bt-error.h" -#include "nm-ip4-config.h" #include "libnm-platform/nm-platform.h" #include "devices/wwan/nm-modem-manager.h" @@ -115,7 +114,7 @@ static NMBluetoothCapabilities get_connection_bt_type(NMConnection *connection) { NMSettingBluetooth *s_bt; - const char * bt_type; + const char *bt_type; s_bt = nm_connection_get_setting_bluetooth(connection); @@ -133,10 +132,10 @@ get_connection_bt_type(NMConnection *connection) } static gboolean -get_connection_bt_type_check(NMDeviceBt * self, - NMConnection * connection, +get_connection_bt_type_check(NMDeviceBt *self, + NMConnection *connection, NMBluetoothCapabilities *out_bt_type, - GError ** error) + GError **error) { NMBluetoothCapabilities bt_type; @@ -170,8 +169,8 @@ get_generic_capabilities(NMDevice *device) static gboolean can_auto_connect(NMDevice *device, NMSettingsConnection *sett_conn, char **specific_object) { - NMDeviceBt * self = NM_DEVICE_BT(device); - NMDeviceBtPrivate * priv = NM_DEVICE_BT_GET_PRIVATE(self); + NMDeviceBt *self = NM_DEVICE_BT(device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); NMBluetoothCapabilities bt_type; nm_assert(!specific_object || !*specific_object); @@ -195,10 +194,10 @@ can_auto_connect(NMDevice *device, NMSettingsConnection *sett_conn, char **speci static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceBt * self = NM_DEVICE_BT(device); - NMDeviceBtPrivate * priv = NM_DEVICE_BT_GET_PRIVATE(self); + NMDeviceBt *self = NM_DEVICE_BT(device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); NMSettingBluetooth *s_bt; - const char * bdaddr; + const char *bdaddr; if (!NM_DEVICE_CLASS(nm_device_bt_parent_class) ->check_connection_compatible(device, connection, error)) @@ -227,14 +226,14 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, +check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { - NMDeviceBt * self = NM_DEVICE_BT(device); - NMDeviceBtPrivate * priv = NM_DEVICE_BT_GET_PRIVATE(self); + NMDeviceBt *self = NM_DEVICE_BT(device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); NMBluetoothCapabilities bt_type; if (!get_connection_bt_type_check(self, connection, &bt_type, error)) @@ -251,23 +250,23 @@ check_connection_available(NMDevice * device, } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { - NMDeviceBtPrivate * priv = NM_DEVICE_BT_GET_PRIVATE(device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device); NMSettingBluetooth *s_bt; - const char * setting_bdaddr; - const char * ctype; + const char *setting_bdaddr; + const char *ctype; gboolean is_dun = FALSE; gboolean is_pan = FALSE; - NMSettingGsm * s_gsm; - NMSettingCdma * s_cdma; - NMSettingSerial * s_serial; - NMSettingPpp * s_ppp; - const char * fallback_prefix = NULL, *preferred = NULL; + NMSettingGsm *s_gsm; + NMSettingCdma *s_cdma; + NMSettingSerial *s_serial; + NMSettingPpp *s_ppp; + const char *fallback_prefix = NULL, *preferred = NULL; s_gsm = nm_connection_get_setting_gsm(connection); s_cdma = nm_connection_get_setting_cdma(connection); @@ -424,44 +423,10 @@ ppp_stats(NMModem *modem, guint i_in_bytes, guint i_out_bytes, gpointer user_dat static void ppp_failed(NMModem *modem, guint i_reason, gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceBt * self = NM_DEVICE_BT(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceStateReason reason = i_reason; - switch (nm_device_get_state(device)) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); - break; - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: - if (nm_device_activate_ip4_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET); - else if (nm_device_activate_ip6_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET6); - else if (nm_device_activate_ip4_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else if (nm_device_activate_ip6_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET6, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else { - _LOGW(LOGD_MB, - "PPP failure in unexpected state %u", - (guint) nm_device_get_state(device)); - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - break; - default: - break; - } + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); } static void @@ -481,7 +446,7 @@ modem_auth_requested(NMModem *modem, gpointer user_data) static void modem_auth_result(NMModem *modem, GError *error, gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device); g_return_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_NEED_AUTH); @@ -498,8 +463,8 @@ modem_auth_result(NMModem *modem, GError *error, gpointer user_data) static void modem_prepare_result(NMModem *modem, gboolean success, guint i_reason, gpointer user_data) { - NMDeviceBt * self = user_data; - NMDeviceBtPrivate * priv = NM_DEVICE_BT_GET_PRIVATE(self); + NMDeviceBt *self = user_data; + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); NMDeviceStateReason reason = i_reason; NMDeviceState state; @@ -528,7 +493,7 @@ modem_prepare_result(NMModem *modem, gboolean success, guint i_reason, gpointer } static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) @@ -547,22 +512,35 @@ device_state_changed(NMDevice * device, } static void -modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data) +modem_new_config(NMModem *modem, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid, + int failure_reason_i, + GError *error, + gpointer user_data) { - NMDeviceBt *self = NM_DEVICE_BT(user_data); - NMDevice * device = NM_DEVICE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDeviceBt *self = NM_DEVICE_BT(user_data); + NMDevice *device = NM_DEVICE(self); - g_return_if_fail(nm_device_activate_ip4_state_in_conf(device) == TRUE); + g_return_if_fail(nm_device_devip_get_state(device, addr_family) == NM_DEVICE_IP_STATE_PENDING); if (error) { - _LOGW(LOGD_MB | LOGD_IP4 | LOGD_BT, - "retrieving IP4 configuration failed: %s", - error->message); - nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + _LOGW(LOGD_MB | LOGD_IP4, "retrieving IP configuration failed: %s", error->message); + nm_device_devip_set_failed(device, addr_family, failure_reason_i); return; } - nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config)); + if (do_auto) { + if (IS_IPv4) + nm_device_ip_method_dhcp4_start(device); + else + nm_device_ip_method_autoconf6_start(device); + } + + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd); } static void @@ -604,7 +582,7 @@ modem_state_cb(NMModem *modem, int new_state_i, int old_state_i, gpointer user_d { NMModemState new_state = new_state_i; NMModemState old_state = old_state_i; - NMDevice * device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceState dev_state = nm_device_get_state(device); if (new_state <= NM_MODEM_STATE_DISABLING && old_state > NM_MODEM_STATE_DISABLING) { @@ -633,7 +611,7 @@ modem_state_cb(NMModem *modem, int new_state_i, int old_state_i, gpointer user_d static void modem_removed_cb(NMModem *modem, gpointer user_data) { - NMDeviceBt * self = NM_DEVICE_BT(user_data); + NMDeviceBt *self = NM_DEVICE_BT(user_data); NMDeviceState state; state = nm_device_get_state(NM_DEVICE(self)); @@ -651,7 +629,7 @@ static gboolean modem_try_claim(NMDeviceBt *self, NMModem *modem) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); - gs_free char * rfcomm_base_name = NULL; + gs_free char *rfcomm_base_name = NULL; NMDeviceState state; if (priv->modem) { @@ -687,7 +665,7 @@ modem_try_claim(NMDeviceBt *self, NMModem *modem) g_signal_connect(modem, NM_MODEM_PPP_STATS, G_CALLBACK(ppp_stats), self); g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self); g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self); - g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self); + g_signal_connect(modem, NM_MODEM_NEW_CONFIG, G_CALLBACK(modem_new_config), self); g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self); g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self); g_signal_connect(modem, NM_MODEM_STATE_CHANGED, G_CALLBACK(modem_state_cb), self); @@ -705,7 +683,7 @@ modem_try_claim(NMDeviceBt *self, NMModem *modem) static void mm_modem_added_cb(NMModemManager *manager, NMModem *modem, gpointer user_data) { - NMDeviceBt * self = user_data; + NMDeviceBt *self = user_data; NMDeviceBtPrivate *priv; if (!modem_try_claim(user_data, modem)) @@ -745,7 +723,7 @@ _nm_device_bt_notify_set_connected(NMDeviceBt *self, gboolean connected) static gboolean connect_watch_link_idle_cb(gpointer user_data) { - NMDeviceBt * self = user_data; + NMDeviceBt *self = user_data; NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); int ifindex; @@ -766,15 +744,15 @@ connect_watch_link_idle_cb(gpointer user_data) } static void -connect_watch_link_cb(NMPlatform * platform, +connect_watch_link_cb(NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink *info, int change_type_i, - NMDevice * self) + NMDevice *self) { const NMPlatformSignalChangeType change_type = change_type_i; - NMDeviceBtPrivate * priv; + NMDeviceBtPrivate *priv; /* bluez doesn't notify us when the connection disconnects. * Neither does NMManager (or NMDevice) tell us when the ip-ifindex goes away. @@ -790,7 +768,7 @@ connect_watch_link_cb(NMPlatform * platform, static gboolean connect_wait_modem_timeout(gpointer user_data) { - NMDeviceBt * self = NM_DEVICE_BT(user_data); + NMDeviceBt *self = NM_DEVICE_BT(user_data); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); /* since this timeout is longer than the connect timeout, we must have already @@ -814,11 +792,11 @@ connect_wait_modem_timeout(gpointer user_data) static void connect_bz_cb(NMBluezManager *bz_mgr, gboolean is_complete, - const char * device_name, - GError * error, + const char *device_name, + GError *error, gpointer user_data) { - NMDeviceBt * self; + NMDeviceBt *self; NMDeviceBtPrivate *priv; char sbuf[100]; @@ -906,10 +884,10 @@ connect_bz_cb(NMBluezManager *bz_mgr, static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceBt * self = NM_DEVICE_BT(device); - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); + NMDeviceBt *self = NM_DEVICE_BT(device); + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); gs_free_error GError *error = NULL; - NMConnection * connection; + NMConnection *connection; connection = nm_device_get_applied_connection(device); g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); @@ -989,38 +967,25 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceBt * self = NM_DEVICE_BT(device); + NMDeviceBt *self = NM_DEVICE_BT(device); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); - if (priv->connect_bt_type == NM_BT_CAPABILITY_DUN) - nm_modem_act_stage2_config(priv->modem); + if (priv->connect_bt_type != NM_BT_CAPABILITY_DUN) + return NM_ACT_STAGE_RETURN_SUCCESS; - return NM_ACT_STAGE_RETURN_SUCCESS; + return nm_modem_act_stage2_config(priv->modem, device, out_failure_reason); } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static void +act_stage3_ip_config(NMDevice *device, int addr_family) { - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device); - gboolean autoip4 = FALSE; - NMActStageReturn ret; + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device); if (priv->connect_bt_type != NM_BT_CAPABILITY_DUN) - goto out_chain_up; - - if (!NM_IS_IPv4(addr_family)) - return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason); - - ret = nm_modem_stage3_ip4_config_start(priv->modem, device, &autoip4, out_failure_reason); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS || !autoip4) - return ret; + return; -out_chain_up: - return NM_DEVICE_CLASS(nm_device_bt_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + if (nm_modem_stage3_ip_config_start(priv->modem, addr_family, device)) + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL); } static void @@ -1070,10 +1035,10 @@ _nm_device_bt_notify_removed(NMDeviceBt *self) /*****************************************************************************/ gboolean -_nm_device_bt_for_same_device(NMDeviceBt * self, - const char * dbus_path, - const char * bdaddr, - const char * name, +_nm_device_bt_for_same_device(NMDeviceBt *self, + const char *dbus_path, + const char *bdaddr, + const char *name, NMBluetoothCapabilities capabilities) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); @@ -1102,7 +1067,7 @@ _nm_device_bt_notify_set_name(NMDeviceBt *self, const char *name) static gboolean is_available(NMDevice *dev, NMDeviceCheckDevAvailableFlags flags) { - NMDeviceBt * self = NM_DEVICE_BT(dev); + NMDeviceBt *self = NM_DEVICE_BT(dev); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); /* PAN doesn't need ModemManager, so devices that support it are always available */ @@ -1206,7 +1171,7 @@ nm_device_bt_init(NMDeviceBt *self) static void constructed(GObject *object) { - NMDeviceBt * self = NM_DEVICE_BT(object); + NMDeviceBt *self = NM_DEVICE_BT(object); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); G_OBJECT_CLASS(nm_device_bt_parent_class)->constructed(object); @@ -1229,10 +1194,10 @@ constructed(GObject *object) } NMDeviceBt * -nm_device_bt_new(NMBluezManager * bz_mgr, - const char * dbus_path, - const char * bdaddr, - const char * name, +nm_device_bt_new(NMBluezManager *bz_mgr, + const char *dbus_path, + const char *bdaddr, + const char *name, NMBluetoothCapabilities capabilities) { g_return_val_if_fail(NM_IS_BLUEZ_MANAGER(bz_mgr), NULL); @@ -1270,7 +1235,7 @@ nm_device_bt_new(NMBluezManager * bz_mgr, static void dispose(GObject *object) { - NMDeviceBt * self = NM_DEVICE_BT(object); + NMDeviceBt *self = NM_DEVICE_BT(object); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(self); nm_clear_g_signal_handler(nm_device_get_platform(NM_DEVICE(self)), @@ -1325,9 +1290,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_bluetooth = { static void nm_device_bt_class_init(NMDeviceBtClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructed = constructed; object_class->get_property = get_property; @@ -1344,7 +1309,7 @@ nm_device_bt_class_init(NMDeviceBtClass *klass) device_class->deactivate = deactivate; device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage3_ip_config = act_stage3_ip_config; device_class->check_connection_compatible = check_connection_compatible; device_class->check_connection_available = check_connection_available; device_class->complete_connection = complete_connection; diff --git a/src/core/devices/bluetooth/nm-device-bt.h b/src/core/devices/bluetooth/nm-device-bt.h index c2d3bc18..59457fba 100644 --- a/src/core/devices/bluetooth/nm-device-bt.h +++ b/src/core/devices/bluetooth/nm-device-bt.h @@ -33,15 +33,15 @@ GType nm_device_bt_get_type(void); struct _NMBluezManager; NMDeviceBt *nm_device_bt_new(struct _NMBluezManager *bz_mgr, - const char * dbus_path, - const char * bdaddr, - const char * name, + const char *dbus_path, + const char *bdaddr, + const char *name, NMBluetoothCapabilities capabilities); -gboolean _nm_device_bt_for_same_device(NMDeviceBt * device, - const char * dbus_path, - const char * bdaddr, - const char * name, +gboolean _nm_device_bt_for_same_device(NMDeviceBt *device, + const char *dbus_path, + const char *bdaddr, + const char *name, NMBluetoothCapabilities capabilities); NMBluetoothCapabilities nm_device_bt_get_capabilities(NMDeviceBt *device); diff --git a/src/core/devices/bluetooth/tests/nm-bt-test.c b/src/core/devices/bluetooth/tests/nm-bt-test.c index 548e7249..5aab48a5 100644 --- a/src/core/devices/bluetooth/tests/nm-bt-test.c +++ b/src/core/devices/bluetooth/tests/nm-bt-test.c @@ -23,8 +23,8 @@ struct { int argc; const char *const *argv; - const char * argv_cmd; - GMainLoop * loop; + const char *argv_cmd; + GMainLoop *loop; } gl; typedef struct _MainCmdInfo { @@ -38,7 +38,7 @@ typedef struct _MainCmdInfo { typedef struct { NMBluez5DunContext *dun_context; - GCancellable * cancellable; + GCancellable *cancellable; guint timeout_id; guint sig_term_id; guint sig_int_id; @@ -46,8 +46,8 @@ typedef struct { static void _dun_connect_cb(NMBluez5DunContext *context, - const char * rfcomm_dev, - GError * error, + const char *rfcomm_dev, + GError *error, gpointer user_data) { DunConnectData *dun_connect_data = user_data; @@ -118,10 +118,10 @@ do_dun_connect(const MainCmdInfo *main_cmd_info) { #if WITH_BLUEZ5_DUN gs_unref_object GCancellable *cancellable = NULL; - gs_free_error GError *error = NULL; - const char * adapter; - const char * remote; - DunConnectData dun_connect_data = {}; + gs_free_error GError *error = NULL; + const char *adapter; + const char *remote; + DunConnectData dun_connect_data = {}; if (gl.argc < 4) { _LOGE("missing arguments \"adapter\" and \"remote\""); diff --git a/src/core/devices/nm-acd-manager.c b/src/core/devices/nm-acd-manager.c deleted file mode 100644 index c041163e..00000000 --- a/src/core/devices/nm-acd-manager.c +++ /dev/null @@ -1,497 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2015 - 2018 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-acd-manager.h" - -#include <netinet/in.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <linux/if_ether.h> - -#include "libnm-platform/nm-platform.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" -#include "n-acd/src/n-acd.h" - -/*****************************************************************************/ - -typedef enum { - STATE_INIT, - STATE_PROBING, - STATE_PROBE_DONE, - STATE_ANNOUNCING, -} State; - -typedef struct { - in_addr_t address; - gboolean duplicate; - NAcdProbe *probe; -} AddressInfo; - -struct _NMAcdManager { - int ifindex; - guint8 hwaddr[ETH_ALEN]; - State state; - GHashTable *addresses; - guint completed; - NAcd * acd; - GSource * event_source; - - NMAcdCallbacks callbacks; - gpointer user_data; -}; - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_IP4 -#define _NMLOG_PREFIX_NAME "acd" -#define _NMLOG(level, ...) \ - G_STMT_START \ - { \ - char _sbuf[64]; \ - \ - nm_log((level), \ - _NMLOG_DOMAIN, \ - self && self->ifindex > 0 \ - ? nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex) \ - : NULL, \ - NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - self ? nm_sprintf_buf(_sbuf, "[%p,%d]", self, self->ifindex) \ - : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static const char * -_acd_event_to_string(unsigned int event) -{ - switch (event) { - case N_ACD_EVENT_READY: - return "ready"; - case N_ACD_EVENT_USED: - return "used"; - case N_ACD_EVENT_DEFENDED: - return "defended"; - case N_ACD_EVENT_CONFLICT: - return "conflict"; - case N_ACD_EVENT_DOWN: - return "down"; - } - return NULL; -} - -#define ACD_EVENT_TO_STRING_BUF_SIZE 50 - -static const char * -_acd_event_to_string_buf(unsigned event, char buffer[static ACD_EVENT_TO_STRING_BUF_SIZE]) -{ - const char *s; - - s = _acd_event_to_string(event); - if (s) - return s; - - g_snprintf(buffer, ACD_EVENT_TO_STRING_BUF_SIZE, "(%u)", event); - return buffer; -} - -static const char * -acd_error_to_string(int error) -{ - if (error < 0) - return nm_strerror_native(-error); - - switch (error) { - case _N_ACD_E_SUCCESS: - return "success"; - case N_ACD_E_PREEMPTED: - return "preempted"; - case N_ACD_E_INVALID_ARGUMENT: - return "invalid argument"; - } - - g_return_val_if_reached(NULL); -} - -static int -acd_error_to_nmerr(int error, gboolean always_fail) -{ - if (error < 0) - return -nm_errno_native(error); - - if (always_fail) { - if (NM_IN_SET(error, N_ACD_E_PREEMPTED, N_ACD_E_INVALID_ARGUMENT)) - return -NME_UNSPEC; - g_return_val_if_reached(-NME_UNSPEC); - } - - /* so, @error is either zero (indicating success) or one - * of the special status codes like N_ACD_E_*. In both cases, - * return the positive value here. */ - if (NM_IN_SET(error, _N_ACD_E_SUCCESS, N_ACD_E_PREEMPTED, N_ACD_E_INVALID_ARGUMENT)) - return error; - - g_return_val_if_reached(error); -} - -/*****************************************************************************/ - -/** - * nm_acd_manager_add_address: - * @self: a #NMAcdManager - * @address: an IP address - * - * Add @address to the list of IP addresses to probe. - - * Returns: %TRUE on success, %FALSE if the address was already in the list - */ -gboolean -nm_acd_manager_add_address(NMAcdManager *self, in_addr_t address) -{ - AddressInfo *info; - - g_return_val_if_fail(self, FALSE); - g_return_val_if_fail(self->state == STATE_INIT, FALSE); - - if (g_hash_table_lookup(self->addresses, GUINT_TO_POINTER(address))) - return FALSE; - - info = g_slice_new0(AddressInfo); - info->address = address; - - g_hash_table_insert(self->addresses, GUINT_TO_POINTER(address), info); - - return TRUE; -} - -static gboolean -acd_event(int fd, GIOCondition condition, gpointer data) -{ - NMAcdManager *self = data; - NAcdEvent * event; - AddressInfo * info; - gboolean emit_probe_terminated = FALSE; - char address_str[INET_ADDRSTRLEN]; - int r; - - if (n_acd_dispatch(self->acd)) - return G_SOURCE_CONTINUE; - - while (!n_acd_pop_event(self->acd, &event) && event) { - char to_string_buffer[ACD_EVENT_TO_STRING_BUF_SIZE]; - gs_free char *hwaddr_str = NULL; - gboolean check_probing_done = FALSE; - char buf[ETH_ALEN * 3]; - - switch (event->event) { - case N_ACD_EVENT_READY: - n_acd_probe_get_userdata(event->ready.probe, (void **) &info); - info->duplicate = FALSE; - if (self->state == STATE_ANNOUNCING) { - /* fake probe ended, start announcing */ - r = n_acd_probe_announce(info->probe, N_ACD_DEFEND_ONCE); - if (r) { - _LOGW("couldn't announce address %s on interface '%s': %s", - _nm_utils_inet4_ntop(info->address, address_str), - nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex), - acd_error_to_string(r)); - } else { - _LOGD("announcing address %s (hw-addr %s)", - _nm_utils_inet4_ntop(info->address, address_str), - _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf))); - } - } - check_probing_done = TRUE; - break; - case N_ACD_EVENT_USED: - n_acd_probe_get_userdata(event->used.probe, (void **) &info); - info->duplicate = TRUE; - check_probing_done = TRUE; - break; - case N_ACD_EVENT_DEFENDED: - n_acd_probe_get_userdata(event->defended.probe, (void **) &info); - _LOGD("defended address %s from host %s", - _nm_utils_inet4_ntop(info->address, address_str), - (hwaddr_str = - nm_utils_hwaddr_ntoa(event->defended.sender, event->defended.n_sender))); - break; - case N_ACD_EVENT_CONFLICT: - n_acd_probe_get_userdata(event->conflict.probe, (void **) &info); - _LOGW("conflict for address %s detected with host %s on interface '%s'", - _nm_utils_inet4_ntop(info->address, address_str), - (hwaddr_str = - nm_utils_hwaddr_ntoa(event->defended.sender, event->defended.n_sender)), - nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex)); - break; - default: - _LOGD("unhandled event '%s'", _acd_event_to_string_buf(event->event, to_string_buffer)); - break; - } - - if (check_probing_done && self->state == STATE_PROBING - && ++self->completed == g_hash_table_size(self->addresses)) { - self->state = STATE_PROBE_DONE; - emit_probe_terminated = TRUE; - } - } - - if (emit_probe_terminated) { - if (self->callbacks.probe_terminated_callback) { - self->callbacks.probe_terminated_callback(self, self->user_data); - } - } - - return G_SOURCE_CONTINUE; -} - -static gboolean -acd_probe_add(NMAcdManager *self, AddressInfo *info, guint64 timeout) -{ - NAcdProbeConfig *probe_config; - int r; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - r = n_acd_probe_config_new(&probe_config); - if (r) { - _LOGW("could not create probe config for %s on interface '%s': %s", - _nm_utils_inet4_ntop(info->address, sbuf), - nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex), - acd_error_to_string(r)); - return FALSE; - } - - n_acd_probe_config_set_ip(probe_config, (struct in_addr){info->address}); - n_acd_probe_config_set_timeout(probe_config, timeout); - - r = n_acd_probe(self->acd, &info->probe, probe_config); - if (r) { - _LOGW("could not start probe for %s on interface '%s': %s", - _nm_utils_inet4_ntop(info->address, sbuf), - nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex), - acd_error_to_string(r)); - n_acd_probe_config_free(probe_config); - return FALSE; - } - - n_acd_probe_set_userdata(info->probe, info); - n_acd_probe_config_free(probe_config); - - return TRUE; -} - -static int -acd_init(NMAcdManager *self) -{ - NAcdConfig *config; - int r; - - if (self->acd) - return 0; - - r = n_acd_config_new(&config); - if (r) - return r; - - n_acd_config_set_ifindex(config, self->ifindex); - n_acd_config_set_transport(config, N_ACD_TRANSPORT_ETHERNET); - n_acd_config_set_mac(config, self->hwaddr, ETH_ALEN); - - r = n_acd_new(&self->acd, config); - n_acd_config_free(config); - return r; -} - -/** - * nm_acd_manager_start_probe: - * @self: a #NMAcdManager - * @timeout: maximum probe duration in milliseconds - * @error: location to store error, or %NULL - * - * Start probing IP addresses for duplicates; when the probe terminates a - * PROBE_TERMINATED signal is emitted. - * - * Returns: 0 on success or a negative NetworkManager error code (NME_*). - */ -int -nm_acd_manager_start_probe(NMAcdManager *self, guint timeout) -{ - GHashTableIter iter; - AddressInfo * info; - gboolean success = FALSE; - int fd, r; - - g_return_val_if_fail(self, FALSE); - g_return_val_if_fail(self->state == STATE_INIT, FALSE); - - r = acd_init(self); - if (r) { - _LOGW("couldn't init ACD for probing on interface '%s': %s", - nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex), - acd_error_to_string(r)); - return acd_error_to_nmerr(r, TRUE); - } - - self->completed = 0; - - g_hash_table_iter_init(&iter, self->addresses); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info)) - success |= acd_probe_add(self, info, timeout); - - if (success) - self->state = STATE_PROBING; - - nm_assert(!self->event_source); - n_acd_get_fd(self->acd, &fd); - self->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, acd_event, self); - - return success ? 0 : -NME_UNSPEC; -} - -/** - * nm_acd_manager_check_address: - * @self: a #NMAcdManager - * @address: an IP address - * - * Check if an IP address is duplicate. @address must have been added with - * nm_acd_manager_add_address(). - * - * Returns: %TRUE if the address is not duplicate, %FALSE otherwise - */ -gboolean -nm_acd_manager_check_address(NMAcdManager *self, in_addr_t address) -{ - AddressInfo *info; - - g_return_val_if_fail(self, FALSE); - g_return_val_if_fail(NM_IN_SET(self->state, STATE_INIT, STATE_PROBE_DONE), FALSE); - - info = g_hash_table_lookup(self->addresses, GUINT_TO_POINTER(address)); - g_return_val_if_fail(info, FALSE); - - return !info->duplicate; -} - -/** - * nm_acd_manager_announce_addresses: - * @self: a #NMAcdManager - * - * Start announcing addresses. - * - * Returns: a negative NetworkManager error number or zero on success. - */ -int -nm_acd_manager_announce_addresses(NMAcdManager *self) -{ - GHashTableIter iter; - AddressInfo * info; - int r; - int fd; - gboolean success = TRUE; - char buf[ETH_ALEN * 3]; - - r = acd_init(self); - if (r) { - _LOGW("couldn't init ACD for announcing addresses on interface '%s': %s", - nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex), - acd_error_to_string(r)); - return acd_error_to_nmerr(r, TRUE); - } - - if (self->state == STATE_INIT) { - /* n-acd can't announce without probing, therefore let's - * start a fake probe with zero timeout and then perform - * the announcement. */ - g_hash_table_iter_init(&iter, self->addresses); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info)) { - if (!acd_probe_add(self, info, 0)) - success = FALSE; - } - self->state = STATE_ANNOUNCING; - } else if (self->state == STATE_ANNOUNCING) { - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - g_hash_table_iter_init(&iter, self->addresses); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info)) { - if (info->duplicate) - continue; - r = n_acd_probe_announce(info->probe, N_ACD_DEFEND_ONCE); - if (r) { - _LOGW("couldn't announce address %s on interface '%s': %s", - _nm_utils_inet4_ntop(info->address, sbuf), - nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex), - acd_error_to_string(r)); - success = FALSE; - } else - _LOGD("announcing address %s (hw-addr %s)", - _nm_utils_inet4_ntop(info->address, sbuf), - _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf))); - } - } - - if (!self->event_source) { - n_acd_get_fd(self->acd, &fd); - self->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, acd_event, self); - } - - return success ? 0 : -NME_UNSPEC; -} - -static void -destroy_address_info(gpointer data) -{ - AddressInfo *info = (AddressInfo *) data; - - n_acd_probe_free(info->probe); - - g_slice_free(AddressInfo, info); -} - -/*****************************************************************************/ - -NMAcdManager * -nm_acd_manager_new(int ifindex, - const guint8 * hwaddr, - guint hwaddr_len, - const NMAcdCallbacks *callbacks, - gpointer user_data) -{ - NMAcdManager *self; - - g_return_val_if_fail(ifindex > 0, NULL); - g_return_val_if_fail(hwaddr, NULL); - g_return_val_if_fail(hwaddr_len == ETH_ALEN, NULL); - - self = g_slice_new0(NMAcdManager); - - if (callbacks) - self->callbacks = *callbacks; - self->user_data = user_data; - - self->addresses = g_hash_table_new_full(nm_direct_hash, NULL, NULL, destroy_address_info); - self->state = STATE_INIT; - self->ifindex = ifindex; - memcpy(self->hwaddr, hwaddr, ETH_ALEN); - return self; -} - -void -nm_acd_manager_free(NMAcdManager *self) -{ - g_return_if_fail(self); - - if (self->callbacks.user_data_destroy) - self->callbacks.user_data_destroy(self->user_data); - - nm_clear_pointer(&self->addresses, g_hash_table_destroy); - nm_clear_g_source_inst(&self->event_source); - nm_clear_pointer(&self->acd, n_acd_unref); - - g_slice_free(NMAcdManager, self); -} diff --git a/src/core/devices/nm-acd-manager.h b/src/core/devices/nm-acd-manager.h deleted file mode 100644 index e8ef6f2b..00000000 --- a/src/core/devices/nm-acd-manager.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2015 - 2018 Red Hat, Inc. - */ - -#ifndef __NM_ACD_MANAGER__ -#define __NM_ACD_MANAGER__ - -#include <netinet/in.h> - -typedef struct _NMAcdManager NMAcdManager; - -typedef struct { - void (*probe_terminated_callback)(NMAcdManager *self, gpointer user_data); - GDestroyNotify user_data_destroy; -} NMAcdCallbacks; - -NMAcdManager *nm_acd_manager_new(int ifindex, - const guint8 * hwaddr, - guint hwaddr_len, - const NMAcdCallbacks *callbacks, - gpointer user_data); - -void nm_acd_manager_free(NMAcdManager *self); - -gboolean nm_acd_manager_add_address(NMAcdManager *self, in_addr_t address); -int nm_acd_manager_start_probe(NMAcdManager *self, guint timeout); -gboolean nm_acd_manager_check_address(NMAcdManager *self, in_addr_t address); -int nm_acd_manager_announce_addresses(NMAcdManager *self); - -NM_AUTO_DEFINE_FCN0(NMAcdManager *, _nm_auto_free_acdmgr, nm_acd_manager_free); -#define nm_auto_free_acdmgr nm_auto(_nm_auto_free_acdmgr) - -#endif /* __NM_ACD_MANAGER__ */ diff --git a/src/core/devices/nm-device-6lowpan.c b/src/core/devices/nm-device-6lowpan.c index 8b77c22c..d6543356 100644 --- a/src/core/devices/nm-device-6lowpan.c +++ b/src/core/devices/nm-device-6lowpan.c @@ -41,7 +41,7 @@ G_DEFINE_TYPE(NMDevice6Lowpan, nm_device_6lowpan, NM_TYPE_DEVICE) /*****************************************************************************/ static void -parent_state_changed(NMDevice * parent, +parent_state_changed(NMDevice *parent, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason, @@ -62,7 +62,7 @@ parent_changed_notify(NMDevice *device, int new_ifindex, NMDevice *new_parent) { - NMDevice6Lowpan * self = NM_DEVICE_6LOWPAN(device); + NMDevice6Lowpan *self = NM_DEVICE_6LOWPAN(device); NMDevice6LowpanPrivate *priv = NM_DEVICE_6LOWPAN_GET_PRIVATE(self); NM_DEVICE_CLASS(nm_device_6lowpan_parent_class) @@ -95,13 +95,13 @@ parent_changed_notify(NMDevice *device, } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); + const char *iface = nm_device_get_iface(device); NMSetting6Lowpan *s_6lowpan; int parent_ifindex; int r; @@ -175,11 +175,11 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSetting6Lowpan *s_6lowpan; @@ -249,7 +249,7 @@ static void nm_device_6lowpan_class_init(NMDevice6LowpanClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_6lowpan); @@ -275,11 +275,11 @@ nm_device_6lowpan_class_init(NMDevice6LowpanClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_6LOWPAN_DEVICE_FACTORY, NM6LowpanDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_6LOWPAN, NM_DEVICE_IFACE, @@ -310,7 +310,7 @@ static char * get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { NMSetting6Lowpan *s_6lowpan; - const char * ifname; + const char *ifname; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_6LOWPAN_SETTING_NAME), NULL); diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index f7d78f57..56b729e9 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -16,7 +16,6 @@ #include "nm-device-factory.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" -#include "nm-ip4-config.h" #include "nm-setting-bond-port.h" #define _NMLOG_DEVICE_TYPE NMDeviceBond @@ -75,11 +74,11 @@ get_generic_capabilities(NMDevice *dev) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { nm_utils_complete_generic(nm_device_get_platform(device), connection, @@ -163,18 +162,18 @@ ignore_option(NMSettingBond *s_bond, const char *option, const char *value) static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceBond * self = NM_DEVICE_BOND(device); + NMDeviceBond *self = NM_DEVICE_BOND(device); NMSettingBond *s_bond = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BOND); int ifindex = nm_device_get_ifindex(device); NMBondMode mode = NM_BOND_MODE_UNKNOWN; - const char ** options; + const char **options; /* Read bond options from sysfs and update the Bond setting to match */ options = nm_setting_bond_get_valid_options(NULL); for (; options[0]; options++) { - const char * option = options[0]; + const char *option = options[0]; gs_free char *value = NULL; - char * p; + char *p; if (NM_IN_STRSET(option, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE)) continue; @@ -216,15 +215,15 @@ update_connection(NMDevice *device, NMConnection *connection) } static gboolean -controller_update_port_connection(NMDevice * self, - NMDevice * port, +controller_update_port_connection(NMDevice *self, + NMDevice *port, NMConnection *connection, - GError ** error) + GError **error) { NMSettingBondPort *s_port; int ifindex_port = nm_device_get_ifindex(port); uint queue_id = NM_BOND_PORT_QUEUE_ID_DEF; - gs_free char * queue_id_str = NULL; + gs_free char *queue_id_str = NULL; g_return_val_if_fail(ifindex_port > 0, FALSE); @@ -252,8 +251,8 @@ static void set_arp_targets(NMDevice *device, const char *cur_arp_ip_target, const char *new_arp_ip_target) { gs_unref_ptrarray GPtrArray *free_list = NULL; - gs_free const char ** cur_strv = NULL; - gs_free const char ** new_strv = NULL; + gs_free const char **cur_strv = NULL; + gs_free const char **new_strv = NULL; gsize cur_len; gsize new_len; gsize i; @@ -311,7 +310,7 @@ static void set_bond_attr_or_default(NMDevice *device, NMSettingBond *s_bond, const char *opt) { NMDeviceBond *self = NM_DEVICE_BOND(device); - const char * value; + const char *value; value = nm_setting_bond_get_option_or_default(s_bond, opt); if (!value) { @@ -353,11 +352,11 @@ set_bond_arp_ip_targets(NMDevice *device, NMSettingBond *s_bond) static gboolean apply_bonding_config(NMDeviceBond *self) { - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMSettingBond *s_bond; NMBondMode mode; - const char * mode_str; - gs_free char * device_bond_mode = NULL; + const char *mode_str; + gs_free char *device_bond_mode = NULL; s_bond = nm_device_get_applied_setting(device, NM_TYPE_SETTING_BOND); g_return_val_if_fail(s_bond, FALSE); @@ -387,7 +386,7 @@ apply_bonding_config(NMDeviceBond *self) static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceBond * self = NM_DEVICE_BOND(device); + NMDeviceBond *self = NM_DEVICE_BOND(device); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; /* Interface must be down to set bond options */ @@ -428,7 +427,7 @@ commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_ static gboolean enslave_slave(NMDevice *device, NMDevice *port, NMConnection *connection, gboolean configure) { - NMDeviceBond * self = NM_DEVICE_BOND(device); + NMDeviceBond *self = NM_DEVICE_BOND(device); NMSettingBondPort *s_port; nm_device_master_check_slave_physical_port(device, port, LOGD_BOND); @@ -479,9 +478,9 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) _LOGD(LOGD_BOND, "bond slave %s is already released", nm_device_get_ip_iface(slave)); if (configure) { - NMConnection * applied; + NMConnection *applied; NMSettingWired *s_wired; - const char * cloned_mac; + const char *cloned_mac; address = g_strdup(nm_device_get_hw_address(device)); @@ -524,11 +523,11 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { const char *iface = nm_device_get_iface(device); int r; @@ -550,12 +549,12 @@ create_and_realize(NMDevice * device, } static gboolean -can_reapply_change(NMDevice * device, +can_reapply_change(NMDevice *device, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { NMDeviceClass *device_class; @@ -563,7 +562,7 @@ can_reapply_change(NMDevice * device, if (nm_streq(setting_name, NM_SETTING_BOND_SETTING_NAME)) { NMSettingBond *s_a = NM_SETTING_BOND(s_old); NMSettingBond *s_b = NM_SETTING_BOND(s_new); - const char ** option_list; + const char **option_list; if (!nm_device_hash_check_invalid_keys(diffs, NM_SETTING_BOND_SETTING_NAME, @@ -602,9 +601,9 @@ can_reapply_change(NMDevice * device, static void reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new) { - NMDeviceBond * self = NM_DEVICE_BOND(device); + NMDeviceBond *self = NM_DEVICE_BOND(device); NMSettingBond *s_bond; - const char * value; + const char *value; NMBondMode mode; NM_DEVICE_CLASS(nm_device_bond_parent_class)->reapply_connection(device, con_old, con_new); @@ -646,7 +645,7 @@ static void nm_device_bond_class_init(NMDeviceBondClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_bond); @@ -677,11 +676,11 @@ nm_device_bond_class_init(NMDeviceBondClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_BOND_DEVICE_FACTORY, NMBondDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_BOND, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 36a73978..4e4c2637 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -48,13 +48,13 @@ get_generic_capabilities(NMDevice *dev) } static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, +check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { - NMDeviceBridge * self = NM_DEVICE_BRIDGE(device); + NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); NMSettingBluetooth *s_bt; if (!NM_DEVICE_CLASS(nm_device_bridge_parent_class) @@ -97,7 +97,7 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMSettingBridge *s_bridge; - const char * mac_address; + const char *mac_address; if (!NM_DEVICE_CLASS(nm_device_bridge_parent_class) ->check_connection_compatible(device, connection, error)) @@ -140,11 +140,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { nm_utils_complete_generic(nm_device_get_platform(device), connection, @@ -290,8 +290,8 @@ typedef struct { #define OPTION(_name, _sysname, ...) \ { \ - .name = ""_name \ - "", \ + .name = ""_name \ + "", \ .sysname = ""_sysname \ "", \ __VA_ARGS__ \ @@ -339,7 +339,6 @@ static const Option master_options[] = { OPTION_TYPE_INT(NM_BRIDGE_AGEING_TIME_MIN, NM_BRIDGE_AGEING_TIME_MAX, NM_BRIDGE_AGEING_TIME_DEF), - .default_if_zero = TRUE, .user_hz_compensate = TRUE, ), OPTION(NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "group_fwd_mask", OPTION_TYPE_INT(0, 0xFFFF, 0), ), OPTION(NM_SETTING_BRIDGE_MULTICAST_HASH_MAX, @@ -433,8 +432,8 @@ commit_option(NMDevice *device, NMSetting *setting, const Option *option, gboole { int ifindex = nm_device_get_ifindex(device); nm_auto_unset_gvalue GValue val = G_VALUE_INIT; - GParamSpec * pspec; - const char * value; + GParamSpec *pspec; + const char *value; char value_buf[100]; if (slave) @@ -522,7 +521,7 @@ static const NMPlatformBridgeVlan ** setting_vlans_to_platform(GPtrArray *array) { NMPlatformBridgeVlan **arr; - NMPlatformBridgeVlan * p_data; + NMPlatformBridgeVlan *p_data; guint i; if (!array || !array->len) @@ -554,8 +553,8 @@ setting_vlans_to_platform(GPtrArray *array) static void commit_slave_options(NMDevice *device, NMSettingBridgePort *setting) { - const Option * option; - NMSetting * s; + const Option *option; + NMSetting *s; gs_unref_object NMSetting *s_clear = NULL; if (setting) @@ -570,11 +569,11 @@ commit_slave_options(NMDevice *device, NMSettingBridgePort *setting) static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceBridge * self = NM_DEVICE_BRIDGE(device); + NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); NMSettingBridge *s_bridge = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BRIDGE); int ifindex = nm_device_get_ifindex(device); - const Option * option; - gs_free char * stp = NULL; + const Option *option; + gs_free char *stp = NULL; int stp_value; option = master_options; @@ -590,8 +589,8 @@ update_connection(NMDevice *device, NMConnection *connection) for (; option->name; option++) { nm_auto_unset_gvalue GValue value = G_VALUE_INIT; - gs_free char * str = NULL; - GParamSpec * pspec; + gs_free char *str = NULL; + GParamSpec *pspec; str = nm_platform_sysctl_master_get_option(nm_device_get_platform(device), ifindex, @@ -665,17 +664,17 @@ out: } static gboolean -master_update_slave_connection(NMDevice * device, - NMDevice * slave, +master_update_slave_connection(NMDevice *device, + NMDevice *slave, NMConnection *connection, - GError ** error) + GError **error) { - NMDeviceBridge * self = NM_DEVICE_BRIDGE(device); + NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); NMSettingConnection *s_con; NMSettingBridgePort *s_port; int ifindex_slave = nm_device_get_ifindex(slave); - const char * iface = nm_device_get_iface(device); - const Option * option; + const char *iface = nm_device_get_iface(device); + const Option *option; g_return_val_if_fail(ifindex_slave > 0, FALSE); @@ -721,14 +720,14 @@ master_update_slave_connection(NMDevice * device, static gboolean bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge) { - NMDeviceBridge * self = NM_DEVICE_BRIDGE(device); - gconstpointer hwaddr; - size_t length; - gboolean enabled; - guint16 pvid; - NMPlatform * plat; - int ifindex; - gs_unref_ptrarray GPtrArray *vlans = NULL; + NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); + gconstpointer hwaddr; + size_t length; + gboolean enabled; + guint16 pvid; + NMPlatform *plat; + int ifindex; + gs_unref_ptrarray GPtrArray *vlans = NULL; gs_free const NMPlatformBridgeVlan **plat_vlans = NULL; if (self->vlan_configured) @@ -796,7 +795,7 @@ static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMConnection *connection; - NMSetting * s_bridge; + NMSetting *s_bridge; const Option *option; connection = nm_device_get_applied_connection(device); @@ -860,9 +859,9 @@ _nm_device_bridge_notify_unregister_bt_nap(NMDevice *device, const char *reason) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceBridge * self = NM_DEVICE_BRIDGE(device); - NMConnection * connection; - NMSettingBluetooth *s_bt; + NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); + NMConnection *connection; + NMSettingBluetooth *s_bt; gs_free_error GError *error = NULL; connection = nm_device_get_applied_connection(device); @@ -922,9 +921,9 @@ deactivate(NMDevice *device) static gboolean enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) { - NMDeviceBridge * self = NM_DEVICE_BRIDGE(device); - NMConnection * master_connection; - NMSettingBridge * s_bridge; + NMDeviceBridge *self = NM_DEVICE_BRIDGE(device); + NMConnection *master_connection; + NMSettingBridge *s_bridge; NMSettingBridgePort *s_port; if (configure) { @@ -943,7 +942,7 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool if (nm_setting_bridge_get_vlan_filtering(s_bridge)) { gs_free const NMPlatformBridgeVlan **plat_vlans = NULL; - gs_unref_ptrarray GPtrArray *vlans = NULL; + gs_unref_ptrarray GPtrArray *vlans = NULL; if (s_port) g_object_get(s_port, NM_SETTING_BRIDGE_PORT_VLANS, &vlans, NULL); @@ -1008,17 +1007,17 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - NMSettingWired * s_wired; - NMSettingBridge * s_bridge; - const char * iface = nm_device_get_iface(device); - const char * hwaddr; - gs_free char * hwaddr_cloned = NULL; + NMSettingWired *s_wired; + NMSettingBridge *s_bridge; + const char *iface = nm_device_get_iface(device); + const char *hwaddr; + gs_free char *hwaddr_cloned = NULL; guint8 mac_address[_NM_UTILS_HWADDR_LEN_MAX]; NMPlatformLnkBridge props; int r; @@ -1062,8 +1061,7 @@ create_and_realize(NMDevice * device, NM_BRIDGE_HELLO_TIME_DEF_SYS), .max_age = _DEFAULT_IF_ZERO(nm_setting_bridge_get_max_age(s_bridge) * 100u, NM_BRIDGE_MAX_AGE_DEF_SYS), - .ageing_time = _DEFAULT_IF_ZERO(nm_setting_bridge_get_ageing_time(s_bridge) * 100u, - NM_BRIDGE_AGEING_TIME_DEF_SYS), + .ageing_time = nm_setting_bridge_get_ageing_time(s_bridge) * 100u, .stp_state = nm_setting_bridge_get_stp(s_bridge), .priority = nm_setting_bridge_get_priority(s_bridge), .vlan_protocol = to_sysfs_vlan_protocol_sys(nm_setting_bridge_get_vlan_protocol(s_bridge)), @@ -1138,7 +1136,7 @@ static void nm_device_bridge_class_init(NMDeviceBridgeClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_bridge); @@ -1172,11 +1170,11 @@ nm_device_bridge_class_init(NMDeviceBridgeClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_BRIDGE_DEVICE_FACTORY, NMBridgeDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_BRIDGE, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c index 4c12648f..de701a0d 100644 --- a/src/core/devices/nm-device-dummy.c +++ b/src/core/devices/nm-device-dummy.c @@ -12,7 +12,6 @@ #include "nm-act-request.h" #include "nm-device-private.h" -#include "nm-ip4-config.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-dummy.h" @@ -43,11 +42,11 @@ get_generic_capabilities(NMDevice *dev) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { nm_utils_complete_generic_with_params(nm_device_get_platform(device), connection, @@ -70,13 +69,13 @@ update_connection(NMDevice *device, NMConnection *connection) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); + const char *iface = nm_device_get_iface(device); NMSettingDummy *s_dummy; int r; @@ -117,7 +116,7 @@ static void nm_device_dummy_class_init(NMDeviceDummyClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_dummy); @@ -140,11 +139,11 @@ nm_device_dummy_class_init(NMDeviceDummyClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DUMMY_DEVICE_FACTORY, NMDummyDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_DUMMY, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 667ea9b9..6e18d119 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -14,38 +14,36 @@ #include <libudev.h> #include <linux/if_ether.h> -#include "libnm-glib-aux/nm-uuid.h" -#include "nm-device-private.h" -#include "nm-act-request.h" -#include "nm-ip4-config.h" #include "NetworkManagerUtils.h" -#include "supplicant/nm-supplicant-manager.h" -#include "supplicant/nm-supplicant-interface.h" -#include "supplicant/nm-supplicant-config.h" -#include "ppp/nm-ppp-manager.h" -#include "ppp/nm-ppp-manager-call.h" -#include "ppp/nm-ppp-status.h" -#include "libnm-platform/nm-platform.h" +#include "NetworkManagerUtils.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-glib-aux/nm-uuid.h" #include "libnm-platform/nm-platform-utils.h" -#include "nm-dcb.h" -#include "settings/nm-settings-connection.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-udev-aux/nm-udev-utils.h" +#include "nm-act-request.h" #include "nm-config.h" +#include "nm-dcb.h" #include "nm-device-ethernet-utils.h" -#include "settings/nm-settings.h" #include "nm-device-factory.h" -#include "libnm-core-aux-intern/nm-libnm-core-utils.h" -#include "libnm-core-intern/nm-core-internal.h" -#include "NetworkManagerUtils.h" -#include "libnm-udev-aux/nm-udev-utils.h" +#include "nm-device-private.h" #include "nm-device-veth.h" +#include "nm-manager.h" +#include "ppp/nm-ppp-mgr.h" +#include "settings/nm-settings-connection.h" +#include "settings/nm-settings.h" +#include "supplicant/nm-supplicant-config.h" +#include "supplicant/nm-supplicant-interface.h" +#include "supplicant/nm-supplicant-manager.h" #define _NMLOG_DEVICE_TYPE NMDeviceEthernet #include "nm-device-logging.h" /*****************************************************************************/ -#define PPPOE_RECONNECT_DELAY 7 -#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */ +#define PPPOE_RECONNECT_DELAY_MSEC 7000 +#define PPPOE_ENCAP_OVERHEAD 8 /* 2 bytes for PPP, 6 for PPPoE */ #define SUPPLICANT_LNK_TIMEOUT_SEC 15 @@ -67,21 +65,21 @@ typedef enum { typedef struct _NMDeviceEthernetPrivate { /* s390 */ - char * subchan1; - char * subchan2; - char * subchan3; - char * subchannels; /* Composite used for checking unmanaged specs */ - char ** subchannels_dbus; /* Array exported on D-Bus */ - char * s390_nettype; + char *subchan1; + char *subchan2; + char *subchan3; + char *subchannels; /* Composite used for checking unmanaged specs */ + char **subchannels_dbus; /* Array exported on D-Bus */ + char *s390_nettype; GHashTable *s390_options; guint32 speed; gulong carrier_id; struct { - NMSupplicantManager * mgr; + NMSupplicantManager *mgr; NMSupplMgrCreateIfaceHandle *create_handle; - NMSupplicantInterface * iface; + NMSupplicantInterface *iface; gulong iface_state_id; gulong auth_state_id; @@ -91,14 +89,16 @@ typedef struct _NMDeviceEthernetPrivate { guint lnk_timeout_id; bool is_associated : 1; + bool ready : 1; } supplicant; NMActRequestGetSecretsCallId *wired_secrets_id; - /* PPPoE */ - NMPPPManager *ppp_manager; - gint32 last_pppoe_time; - guint pppoe_wait_id; + struct { + NMPppMgr *ppp_mgr; + GSource *wait_source; + gint64 last_pppoe_time_msec; + } ppp_data; /* DCB */ DcbWait dcb_wait; @@ -113,6 +113,8 @@ typedef struct _NMDeviceEthernetPrivate { bool ethtool_prev_set : 1; bool ethtool_prev_autoneg : 1; + bool stage2_ready_dcb : 1; + } NMDeviceEthernetPrivate; NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceEthernet, PROP_SPEED, PROP_S390_SUBCHANNELS, ); @@ -150,12 +152,12 @@ static void _update_s390_subchannels(NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - struct udev_device * dev = NULL; - struct udev_device * parent = NULL; - const char * parent_path, *item; + struct udev_device *dev = NULL; + struct udev_device *parent = NULL; + const char *parent_path, *item; int ifindex; - GDir * dir; - GError * error = NULL; + GDir *dir; + GError *error = NULL; if (priv->subchannels) { /* only read the subchannels once. For one, we don't expect them to change @@ -251,7 +253,7 @@ _update_s390_subchannels(NMDeviceEthernet *self) } static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) @@ -306,7 +308,7 @@ static gboolean match_subchans(NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - const char *const * subchans; + const char *const *subchans; guint32 num1, num2; int i; @@ -345,7 +347,7 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); - NMSettingWired * s_wired; + NMSettingWired *s_wired; if (!NM_DEVICE_CLASS(nm_device_ethernet_parent_class) ->check_connection_compatible(device, connection, error)) @@ -363,7 +365,7 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } if (s_wired) { - const char * mac, *perm_hw_addr; + const char *mac, *perm_hw_addr; gboolean try_mac = TRUE; const char *const *mac_blacklist; int i; @@ -428,6 +430,7 @@ supplicant_interface_release(NMDeviceEthernet *self) nm_clear_g_source(&priv->supplicant.con_timeout_id); nm_clear_g_signal_handler(priv->supplicant.iface, &priv->supplicant.iface_state_id); nm_clear_g_signal_handler(priv->supplicant.iface, &priv->supplicant.auth_state_id); + priv->supplicant.ready = FALSE; if (priv->supplicant.iface) { nm_supplicant_interface_disconnect(priv->supplicant.iface); @@ -437,8 +440,8 @@ supplicant_interface_release(NMDeviceEthernet *self) static void supplicant_auth_state_changed(NMSupplicantInterface *iface, - GParamSpec * pspec, - NMDeviceEthernet * self) + GParamSpec *pspec, + NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); NMSupplicantAuthState state; @@ -466,40 +469,39 @@ static void wired_auth_cond_fail(NMDeviceEthernet *self, NMDeviceStateReason reason) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - - if (wired_auth_is_optional(self)) { - _LOGI( - LOGD_DEVICE | LOGD_ETHER, - "Activation: (ethernet) 802.1X authentication is optional, continuing after a failure"); - if (NM_IN_SET(nm_device_get_state(device), - NM_DEVICE_STATE_CONFIG, - NM_DEVICE_STATE_NEED_AUTH)) - nm_device_activate_schedule_stage3_ip_config_start(device); - - if (!priv->supplicant.auth_state_id) { - priv->supplicant.auth_state_id = - g_signal_connect(priv->supplicant.iface, - "notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE, - G_CALLBACK(supplicant_auth_state_changed), - self); - } + NMDevice *device = NM_DEVICE(self); + + if (!wired_auth_is_optional(self)) { + supplicant_interface_release(self); + nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason); return; } - supplicant_interface_release(self); - nm_device_state_changed(NM_DEVICE(self), NM_DEVICE_STATE_FAILED, reason); + _LOGI(LOGD_DEVICE | LOGD_ETHER, + "Activation: (ethernet) 802.1X authentication is optional, continuing after a failure"); + priv->supplicant.ready = TRUE; + + if (NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH)) + nm_device_activate_schedule_stage2_device_config(device, FALSE); + + if (!priv->supplicant.auth_state_id) { + priv->supplicant.auth_state_id = + g_signal_connect(priv->supplicant.iface, + "notify::" NM_SUPPLICANT_INTERFACE_AUTH_STATE, + G_CALLBACK(supplicant_auth_state_changed), + self); + } } static void -wired_secrets_cb(NMActRequest * req, +wired_secrets_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * connection, - GError * error, + NMSettingsConnection *connection, + GError *error, gpointer user_data) { - NMDeviceEthernet * self = user_data; - NMDevice * device = user_data; + NMDeviceEthernet *self = user_data; + NMDevice *device = user_data; NMDeviceEthernetPrivate *priv; g_return_if_fail(NM_IS_DEVICE_ETHERNET(self)); @@ -539,12 +541,12 @@ wired_secrets_cancel(NMDeviceEthernet *self) } static void -wired_secrets_get_secrets(NMDeviceEthernet * self, - const char * setting_name, +wired_secrets_get_secrets(NMDeviceEthernet *self, + const char *setting_name, NMSecretAgentGetSecretsFlags flags) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMActRequest * req; + NMActRequest *req; wired_secrets_cancel(self); @@ -559,12 +561,12 @@ wired_secrets_get_secrets(NMDeviceEthernet * self, static gboolean supplicant_lnk_timeout_cb(gpointer user_data) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - NMActRequest * req; - NMConnection * applied_connection; - const char * setting_name; + NMDevice *device = NM_DEVICE(self); + NMActRequest *req; + NMConnection *applied_connection; + const char *setting_name; priv->supplicant.lnk_timeout_id = 0; @@ -611,10 +613,10 @@ time_out: static NMSupplicantConfig * build_supplicant_config(NMDeviceEthernet *self, GError **error) { - const char * con_uuid; + const char *con_uuid; NMSupplicantConfig *config = NULL; - NMSetting8021x * security; - NMConnection * connection; + NMSetting8021x *security; + NMConnection *connection; guint32 mtu; connection = nm_device_get_applied_connection(NM_DEVICE(self)); @@ -644,14 +646,15 @@ supplicant_iface_state_is_completed(NMDeviceEthernet *self, NMSupplicantInterfac if (state == NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) { nm_clear_g_source(&priv->supplicant.lnk_timeout_id); nm_clear_g_source(&priv->supplicant.con_timeout_id); + priv->supplicant.ready = TRUE; /* If this is the initial association during device activation, - * schedule the next activation stage. + * schedule the activation stage again to proceed. */ if (nm_device_get_state(NM_DEVICE(self)) == NM_DEVICE_STATE_CONFIG) { _LOGI(LOGD_DEVICE | LOGD_ETHER, "Activation: (ethernet) Stage 2 of 5 (Device Configure) successful."); - nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self)); + nm_device_activate_schedule_stage2_device_config(NM_DEVICE(self), FALSE); } return; } @@ -664,7 +667,7 @@ supplicant_iface_state_is_completed(NMDeviceEthernet *self, NMSupplicantInterfac static void supplicant_iface_assoc_cb(NMSupplicantInterface *iface, GError *error, gpointer user_data) { - NMDeviceEthernet * self; + NMDeviceEthernet *self; NMDeviceEthernetPrivate *priv; if (nm_utils_error_is_cancelled_or_disposing(error)) @@ -692,9 +695,9 @@ supplicant_iface_assoc_cb(NMSupplicantInterface *iface, GError *error, gpointer static gboolean supplicant_iface_start(NMDeviceEthernet *self) { - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); gs_unref_object NMSupplicantConfig *config = NULL; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; config = build_supplicant_config(self, &error); if (!config) { @@ -720,8 +723,8 @@ supplicant_iface_state_cb(NMSupplicantInterface *iface, int disconnect_reason, gpointer user_data) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data); - NMDeviceEthernetPrivate * priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); NMSupplicantInterfaceState new_state = new_state_i; NMSupplicantInterfaceState old_state = old_state_i; @@ -750,7 +753,7 @@ supplicant_iface_state_cb(NMSupplicantInterface *iface, static gboolean handle_auth_or_fail(NMDeviceEthernet *self, NMActRequest *req, gboolean new_secrets) { - const char * setting_name; + const char *setting_name; NMConnection *applied_connection; if (!nm_device_auth_retries_try_next(NM_DEVICE(self))) @@ -789,11 +792,11 @@ handle_auth_or_fail(NMDeviceEthernet *self, NMActRequest *req, gboolean new_secr static gboolean supplicant_connection_timeout_cb(gpointer user_data) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - NMActRequest * req; - NMSettingsConnection * connection; + NMDevice *device = NM_DEVICE(self); + NMActRequest *req; + NMSettingsConnection *connection; guint64 timestamp = 0; gboolean new_secrets = TRUE; @@ -833,13 +836,13 @@ supplicant_connection_timeout_cb(gpointer user_data) } static void -supplicant_interface_create_cb(NMSupplicantManager * supplicant_manager, +supplicant_interface_create_cb(NMSupplicantManager *supplicant_manager, NMSupplMgrCreateIfaceHandle *handle, - NMSupplicantInterface * iface, - GError * error, + NMSupplicantInterface *iface, + GError *error, gpointer user_data) { - NMDeviceEthernet * self; + NMDeviceEthernet *self; NMDeviceEthernetPrivate *priv; guint timeout; @@ -894,9 +897,9 @@ link_duplex_to_platform(const char *duplex) static void link_negotiation_set(NMDevice *device) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMSettingWired * s_wired; + NMSettingWired *s_wired; gboolean autoneg = TRUE; gboolean link_autoneg; NMPlatformLinkDuplexType duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; @@ -966,20 +969,20 @@ link_negotiation_set(NMDevice *device) static gboolean pppoe_reconnect_delay(gpointer user_data) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - priv->pppoe_wait_id = 0; - priv->last_pppoe_time = 0; + nm_clear_g_source_inst(&priv->ppp_data.wait_source); + priv->ppp_data.last_pppoe_time_msec = 0; _LOGI(LOGD_DEVICE, "PPPoE reconnect delay complete, resuming connection..."); nm_device_activate_schedule_stage1_device_prepare(NM_DEVICE(self), FALSE); - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); if (nm_device_sys_iface_state_is_external_or_assume(device)) { @@ -1014,21 +1017,24 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) * at least for additional NM_SHUTDOWN_TIMEOUT_MS seconds because * otherwise after restart the device won't work for the first seconds. */ - if (priv->last_pppoe_time != 0) { - gint32 delay = nm_utils_get_monotonic_timestamp_sec() - priv->last_pppoe_time; + if (priv->ppp_data.last_pppoe_time_msec != 0) { + gint64 delay = + nm_utils_get_monotonic_timestamp_msec() - priv->ppp_data.last_pppoe_time_msec; - if (delay < PPPOE_RECONNECT_DELAY + if (delay < PPPOE_RECONNECT_DELAY_MSEC && nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE)) { - if (priv->pppoe_wait_id == 0) { + if (!priv->ppp_data.wait_source) { _LOGI(LOGD_DEVICE, - "delaying PPPoE reconnect for %d seconds to ensure peer is ready...", - delay); - priv->pppoe_wait_id = g_timeout_add_seconds(delay, pppoe_reconnect_delay, self); + "delaying PPPoE reconnect for %d.%03d seconds to ensure peer is ready...", + (int) (delay / 1000), + (int) (delay % 1000)); + priv->ppp_data.wait_source = + nm_g_timeout_add_source(delay, pppoe_reconnect_delay, self); } return NM_ACT_STAGE_RETURN_POSTPONE; } - nm_clear_g_source(&priv->pppoe_wait_id); - priv->last_pppoe_time = 0; + nm_clear_g_source_inst(&priv->ppp_data.wait_source); + priv->ppp_data.last_pppoe_time_msec = 0; } return NM_ACT_STAGE_RETURN_SUCCESS; @@ -1038,9 +1044,9 @@ static NMActStageReturn supplicant_check_secrets_needed(NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMConnection * connection; - NMSetting8021x * security; - const char * setting_name; + NMConnection *connection; + NMSetting8021x *security; + const char *setting_name; connection = nm_device_get_applied_connection(NM_DEVICE(self)); g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); @@ -1105,105 +1111,79 @@ carrier_changed(NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceEtherne } /*****************************************************************************/ -/* PPPoE */ static void -ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +_ppp_mgr_cleanup(NMDeviceEthernet *self) { - NMDevice *device = NM_DEVICE(user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } + nm_clear_pointer(&priv->ppp_data.ppp_mgr, nm_ppp_mgr_destroy); } static void -ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data) +_ppp_mgr_stage3_maybe_ready(NMDeviceEthernet *self) { - NMDevice *device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(self); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); + int IS_IPv4; - if (!nm_device_set_ip_ifindex(device, ifindex)) { - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } -} + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; + const NMPppMgrIPData *ip_data; -static void -ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) -{ - NMDevice *device = NM_DEVICE(user_data); + ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_data.ppp_mgr, addr_family); + if (ip_data->ip_received) + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd); + } - /* Ignore PPP IP4 events that come in after initial configuration */ - if (nm_device_activate_ip4_state_in_conf(device)) - nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config)); + if (nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG) + nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL); } -static NMActStageReturn -pppoe_stage3_ip4_config_start(NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason) +static void +_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data) { - NMDevice * device = NM_DEVICE(self); - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMSettingPppoe * s_pppoe; - NMActRequest * req; - GError * err = NULL; - - req = nm_device_get_act_request(device); - - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); - - s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data); + NMDevice *device = NM_DEVICE(self); + NMDeviceState device_state; - g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); + if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED) + return; - priv->ppp_manager = nm_ppp_manager_create(nm_device_get_iface(device), &err); + device_state = nm_device_get_state(device); - if (priv->ppp_manager) { - nm_ppp_manager_set_route_parameters(priv->ppp_manager, - nm_device_get_route_table(device, AF_INET), - nm_device_get_route_metric(device, AF_INET), - nm_device_get_route_table(device, AF_INET6), - nm_device_get_route_metric(device, AF_INET6)); + if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) { + if (device_state <= NM_DEVICE_STATE_ACTIVATED) + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason); + return; } - if (!priv->ppp_manager - || !nm_ppp_manager_start(priv->ppp_manager, - req, - nm_setting_pppoe_get_username(s_pppoe), - 30, - 0, - &err)) { - _LOGW(LOGD_DEVICE, "PPPoE failed to start: %s", err->message); - g_error_free(err); + if (device_state < NM_DEVICE_STATE_IP_CONFIG) { + if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) { + gs_free char *old_name = NULL; + gs_free_error GError *error = NULL; + + if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) { + _LOGW(LOGD_DEVICE | LOGD_PPP, + "could not take control of link %d: %s", + callback_data->data.ifindex, + error->message); + _ppp_mgr_cleanup(self); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } - g_clear_object(&priv->ppp_manager); + if (old_name) + nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; + nm_device_activate_schedule_stage2_device_config(device, FALSE); + } + return; } - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, - G_CALLBACK(ppp_state_changed), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK(ppp_ifindex_set), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, - G_CALLBACK(ppp_ip4_config), - self); - return NM_ACT_STAGE_RETURN_POSTPONE; + _ppp_mgr_stage3_maybe_ready(self); } /*****************************************************************************/ @@ -1213,9 +1193,9 @@ static void dcb_state(NMDevice *device, gboolean timeout); static gboolean dcb_carrier_timeout(gpointer user_data) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(user_data); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(user_data); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); g_return_val_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG, G_SOURCE_REMOVE); @@ -1230,10 +1210,10 @@ dcb_carrier_timeout(gpointer user_data) static gboolean dcb_configure(NMDevice *device) { - NMDeviceEthernet * self = (NMDeviceEthernet *) device; + NMDeviceEthernet *self = (NMDeviceEthernet *) device; NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMSettingDcb * s_dcb; - GError * error = NULL; + NMSettingDcb *s_dcb; + GError *error = NULL; nm_clear_g_source(&priv->dcb_timeout_id); @@ -1259,9 +1239,9 @@ dcb_configure(NMDevice *device) static gboolean dcb_enable(NMDevice *device) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - GError * error = NULL; + GError *error = NULL; nm_clear_g_source(&priv->dcb_timeout_id); if (!nm_dcb_enable(nm_device_get_iface(device), TRUE, &error)) { @@ -1286,7 +1266,7 @@ dcb_enable(NMDevice *device) static void dcb_state(NMDevice *device, gboolean timeout) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); gboolean carrier; @@ -1351,7 +1331,7 @@ dcb_state(NMDevice *device, gboolean timeout) nm_clear_g_source(&priv->dcb_timeout_id); priv->dcb_handle_carrier_changes = FALSE; priv->dcb_wait = DCB_WAIT_UNKNOWN; - nm_device_activate_schedule_stage3_ip_config_start(device); + nm_device_activate_schedule_stage2_device_config(device, FALSE); } break; default: @@ -1365,8 +1345,8 @@ static gboolean wake_on_lan_enable(NMDevice *device) { NMSettingWiredWakeOnLan wol; - NMSettingWired * s_wired; - const char * password = NULL; + NMSettingWired *s_wired; + const char *password = NULL; s_wired = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRED); @@ -1407,31 +1387,98 @@ found: static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceEthernet * self = (NMDeviceEthernet *) device; + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMSettingConnection * s_con; - const char * connection_type; - gboolean do_postpone = FALSE; - NMSettingDcb * s_dcb; + NMConnection *connection; + NMSettingConnection *s_con; + const char *connection_type; + NMSettingDcb *s_dcb; + NMActRequest *req; - s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION); + connection = nm_device_get_applied_connection(device); + g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + s_con = _nm_connection_get_setting(connection, NM_TYPE_SETTING_CONNECTION); g_return_val_if_fail(s_con, NM_ACT_STAGE_RETURN_FAILURE); nm_clear_g_source(&priv->dcb_timeout_id); priv->dcb_handle_carrier_changes = FALSE; + connection_type = nm_setting_connection_get_connection_type(s_con); + + if (nm_streq(connection_type, NM_SETTING_PPPOE_SETTING_NAME)) { + if (!priv->ppp_data.ppp_mgr) { + gs_free_error GError *error = NULL; + NMSettingPppoe *s_pppoe; + NMSettingPpp *s_ppp; + + s_ppp = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPP); + if (s_ppp) { + guint32 mtu; + guint32 mru; + guint32 mxu; + + mtu = nm_setting_ppp_get_mtu(s_ppp); + mru = nm_setting_ppp_get_mru(s_ppp); + mxu = MAX(mru, mtu); + if (mxu) { + _LOGD(LOGD_PPP, + "set MTU to %u (PPP interface MRU %u, MTU %u)", + mxu + PPPOE_ENCAP_OVERHEAD, + mru, + mtu); + nm_platform_link_set_mtu(nm_device_get_platform(device), + nm_device_get_ifindex(device), + mxu + PPPOE_ENCAP_OVERHEAD); + } + } + + req = nm_device_get_act_request(device); + g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); + + s_pppoe = _nm_connection_get_setting(connection, NM_TYPE_SETTING_PPPOE); + g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); + + priv->ppp_data.ppp_mgr = + nm_ppp_mgr_start(&((const NMPppMgrConfig){ + .netns = nm_device_get_netns(device), + .parent_iface = nm_device_get_iface(device), + .callback = _ppp_mgr_callback, + .user_data = self, + .act_req = req, + .ppp_username = nm_setting_pppoe_get_username(s_pppoe), + .timeout_secs = 30, + .baud_override = 0, + }), + &error); + if (!priv->ppp_data.ppp_mgr) { + _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message); + *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + if (nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX) + return NM_ACT_STAGE_RETURN_POSTPONE; + } + /* 802.1x has to run before any IP configuration since the 802.1x auth * process opens the port up for normal traffic. */ - connection_type = nm_setting_connection_get_connection_type(s_con); if (nm_streq(connection_type, NM_SETTING_WIRED_SETTING_NAME)) { NMSetting8021x *security; security = nm_device_get_applied_setting(device, NM_TYPE_SETTING_802_1X); if (security) { - /* FIXME: for now 802.1x is mutually exclusive with DCB */ + /* FIXME: we always return from this. stage2 must be re-entrant, and + * process all the necessary steps. Just returning for 8021x is wrong. */ + + if (priv->supplicant.ready) + return NM_ACT_STAGE_RETURN_SUCCESS; + if (!nm_device_has_carrier(NM_DEVICE(self))) { _LOGD(LOGD_DEVICE | LOGD_ETHER, "delay supplicant initialization until carrier goes up"); @@ -1450,7 +1497,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) /* DCB and FCoE setup */ s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB); - if (s_dcb) { + if (!priv->stage2_ready_dcb && s_dcb) { /* lldpad really really wants the carrier to be up */ if (nm_platform_link_is_connected(nm_device_get_platform(device), nm_device_get_ifindex(device))) { @@ -1465,100 +1512,66 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) } priv->dcb_handle_carrier_changes = TRUE; - do_postpone = TRUE; - } - - /* PPPoE setup */ - if (nm_connection_is_type(nm_device_get_applied_connection(device), - NM_SETTING_PPPOE_SETTING_NAME)) { - NMSettingPpp *s_ppp; - - s_ppp = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPP); - if (s_ppp) { - guint32 mtu; - guint32 mru; - guint32 mxu; - - mtu = nm_setting_ppp_get_mtu(s_ppp); - mru = nm_setting_ppp_get_mru(s_ppp); - mxu = MAX(mru, mtu); - if (mxu) { - _LOGD(LOGD_PPP, - "set MTU to %u (PPP interface MRU %u, MTU %u)", - mxu + PPPOE_ENCAP_OVERHEAD, - mru, - mtu); - nm_platform_link_set_mtu(nm_device_get_platform(device), - nm_device_get_ifindex(device), - mxu + PPPOE_ENCAP_OVERHEAD); - } - } + return NM_ACT_STAGE_RETURN_POSTPONE; } - return do_postpone ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_SUCCESS; + return NM_ACT_STAGE_RETURN_SUCCESS; } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static guint32 +get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force) { - NMSettingConnection *s_con; - const char * connection_type; - int ifindex; + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device); - ifindex = nm_device_get_ifindex(device); + /* MTU only set for plain ethernet */ + if (priv->ppp_data.ppp_mgr) + return 0; - if (ifindex <= 0) - return NM_ACT_STAGE_RETURN_FAILURE; + return nm_device_get_configured_mtu_for_wired(device, out_source, out_force); +} - if (addr_family == AF_INET) { - s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION); +static void +act_stage3_ip_config(NMDevice *device, int addr_family) +{ + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); + NMPppMgrState ppp_state; - g_return_val_if_fail(s_con, NM_ACT_STAGE_RETURN_FAILURE); + if (!priv->ppp_data.ppp_mgr) + return; - connection_type = nm_setting_connection_get_connection_type(s_con); - if (!strcmp(connection_type, NM_SETTING_PPPOE_SETTING_NAME)) - return pppoe_stage3_ip4_config_start(NM_DEVICE_ETHERNET(device), out_failure_reason); - } + ppp_state = nm_ppp_mgr_get_state(priv->ppp_data.ppp_mgr); - return NM_DEVICE_CLASS(nm_device_ethernet_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); -} + nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG)); -static guint32 -get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force) -{ - /* MTU only set for plain ethernet */ - if (NM_DEVICE_ETHERNET_GET_PRIVATE(device)->ppp_manager) - return 0; + if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) { + nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL); + return; + } - return nm_device_get_configured_mtu_for_wired(device, out_source, out_force); + _ppp_mgr_stage3_maybe_ready(self); } static void deactivate(NMDevice *device) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); - NMSettingDcb * s_dcb; - GError * error = NULL; + NMSettingDcb *s_dcb; + GError *error = NULL; int ifindex; - nm_clear_g_source(&priv->pppoe_wait_id); + nm_clear_g_source_inst(&priv->ppp_data.wait_source); nm_clear_g_signal_handler(self, &priv->carrier_id); - if (priv->ppp_manager) { - nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL); - g_clear_object(&priv->ppp_manager); - } + _ppp_mgr_cleanup(self); supplicant_interface_release(self); priv->dcb_wait = DCB_WAIT_UNKNOWN; nm_clear_g_source(&priv->dcb_timeout_id); priv->dcb_handle_carrier_changes = FALSE; + priv->stage2_ready_dcb = FALSE; /* Tear down DCB/FCoE if it was enabled */ s_dcb = nm_device_get_applied_setting(device, NM_TYPE_SETTING_DCB); @@ -1571,7 +1584,7 @@ deactivate(NMDevice *device) /* Set last PPPoE connection time */ if (nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE)) - priv->last_pppoe_time = nm_utils_get_monotonic_timestamp_sec(); + priv->ppp_data.last_pppoe_time_msec = nm_utils_get_monotonic_timestamp_msec(); ifindex = nm_device_get_ifindex(device); if (ifindex > 0 && priv->ethtool_prev_set) { @@ -1594,19 +1607,19 @@ deactivate(NMDevice *device) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingWired *s_wired; NMSettingPppoe *s_pppoe; if (nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_VETH_SETTING_NAME)) { NMSettingVeth *s_veth; - const char * peer_name = NULL; - const char * con_peer_name = NULL; + const char *peer_name = NULL; + const char *con_peer_name = NULL; int ifindex; nm_utils_complete_generic(nm_device_get_platform(device), @@ -1683,16 +1696,16 @@ complete_connection(NMDevice * device, static NMConnection * new_default_connection(NMDevice *self) { - NMConnection * connection; - NMSettingsConnection *const *connections; - NMSetting * setting; + NMConnection *connection; + NMSettingsConnection *const *connections; + NMSetting *setting; gs_unref_hashtable GHashTable *existing_ids = NULL; - struct udev_device * dev; - const char * perm_hw_addr; - const char * iface; - const char * uprop = "0"; - gs_free char * defname = NULL; - gs_free char * uuid = NULL; + struct udev_device *dev; + const char *perm_hw_addr; + const char *iface; + const char *uprop = "0"; + gs_free char *defname = NULL; + gs_free char *uuid = NULL; guint i, n_connections; perm_hw_addr = nm_device_get_permanent_hw_address(self); @@ -1778,12 +1791,12 @@ update_connection(NMDevice *device, NMConnection *connection) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(device); NMSettingWired *s_wired = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRED); gboolean perm_hw_addr_is_fake; - const char * perm_hw_addr; - const char * mac = nm_device_get_hw_address(device); - const char * mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; + const char *perm_hw_addr; + const char *mac = nm_device_get_hw_address(device); + const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS; GHashTableIter iter; - const char * key; - const char * value; + const char *key; + const char *value; g_object_set(nm_connection_get_setting_connection(connection), NM_SETTING_CONNECTION_TYPE, @@ -1823,7 +1836,7 @@ update_connection(NMDevice *device, NMConnection *connection) static void link_speed_update(NMDevice *device) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); guint32 speed; @@ -1844,7 +1857,7 @@ link_speed_update(NMDevice *device) static void carrier_changed_notify(NMDevice *device, gboolean carrier) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(device); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); if (priv->dcb_handle_carrier_changes) { @@ -1880,12 +1893,12 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) } static gboolean -can_reapply_change(NMDevice * device, +can_reapply_change(NMDevice *device, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { NMDeviceClass *device_class; @@ -1926,14 +1939,14 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne static void dispose(GObject *object) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(object); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); wired_secrets_cancel(self); supplicant_interface_release(self); - nm_clear_g_source(&priv->pppoe_wait_id); + nm_clear_g_source_inst(&priv->ppp_data.wait_source); nm_clear_g_source(&priv->dcb_timeout_id); @@ -1945,7 +1958,7 @@ dispose(GObject *object) static void finalize(GObject *object) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(object); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); g_clear_object(&priv->supplicant.mgr); @@ -1963,7 +1976,7 @@ finalize(GObject *object) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceEthernet * self = NM_DEVICE_ETHERNET(object); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET(object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); switch (prop_id) { @@ -2007,9 +2020,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_wired = { static void nm_device_ethernet_class_init(NMDeviceEthernetClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); g_type_class_add_private(object_class, sizeof(NMDeviceEthernetPrivate)); @@ -2032,7 +2045,7 @@ nm_device_ethernet_class_init(NMDeviceEthernetClass *klass) device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage1_prepare_set_hwaddr_ethernet = TRUE; device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage3_ip_config = act_stage3_ip_config; device_class->get_configured_mtu = get_configured_mtu; device_class->deactivate = deactivate; device_class->get_s390_subchannels = get_s390_subchannels; @@ -2070,11 +2083,11 @@ nm_device_ethernet_class_init(NMDeviceEthernetClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_ETHERNET_DEVICE_FACTORY, NMEthernetDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_ETHERNET, NM_DEVICE_IFACE, @@ -2091,7 +2104,7 @@ create_device(NMDeviceFactory * factory, static gboolean match_connection(NMDeviceFactory *factory, NMConnection *connection) { - const char * type = nm_connection_get_connection_type(connection); + const char *type = nm_connection_get_connection_type(connection); NMSettingPppoe *s_pppoe; if (nm_streq(type, NM_SETTING_WIRED_SETTING_NAME)) diff --git a/src/core/devices/nm-device-factory.c b/src/core/devices/nm-device-factory.c index bdc64135..41e9480f 100644 --- a/src/core/devices/nm-device-factory.c +++ b/src/core/devices/nm-device-factory.c @@ -29,8 +29,8 @@ G_DEFINE_ABSTRACT_TYPE(NMDeviceFactory, nm_device_factory, G_TYPE_OBJECT) /*****************************************************************************/ static void -nm_device_factory_get_supported_types(NMDeviceFactory * factory, - const NMLinkType ** out_link_types, +nm_device_factory_get_supported_types(NMDeviceFactory *factory, + const NMLinkType **out_link_types, const char *const **out_setting_types) { g_return_if_fail(NM_IS_DEVICE_FACTORY(factory)); @@ -50,15 +50,15 @@ nm_device_factory_start(NMDeviceFactory *factory) } NMDevice * -nm_device_factory_create_device(NMDeviceFactory * factory, - const char * iface, +nm_device_factory_create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore, - GError ** error) + NMConnection *connection, + gboolean *out_ignore, + GError **error) { NMDeviceFactoryClass *klass; - NMDevice * device; + NMDevice *device; gboolean ignore = FALSE; g_return_val_if_fail(factory, NULL); @@ -121,12 +121,12 @@ nm_device_factory_get_connection_parent(NMDeviceFactory *factory, NMConnection * char * nm_device_factory_get_connection_iface(NMDeviceFactory *factory, - NMConnection * connection, - const char * parent_iface, - GError ** error) + NMConnection *connection, + const char *parent_iface, + GError **error) { NMDeviceFactoryClass *klass; - char * ifname; + char *ifname; g_return_val_if_fail(factory != NULL, NULL); g_return_val_if_fail(connection != NULL, NULL); @@ -196,9 +196,9 @@ NMDeviceFactory * nm_device_factory_manager_find_factory_for_connection(NMConnection *connection) { NMDeviceFactoryClass *klass; - NMDeviceFactory * factory; - const char * type; - GSList * list; + NMDeviceFactory *factory; + const char *type; + GSList *list; g_return_val_if_fail(factories_by_setting, NULL); @@ -221,7 +221,7 @@ nm_device_factory_manager_for_each_factory(NMDeviceFactoryManagerFactoryFunc cal { GHashTableIter iter; NMDeviceFactory *factory; - GSList * list_iter, *list = NULL; + GSList *list_iter, *list = NULL; if (factories_by_link) { g_hash_table_iter_init(&iter, factories_by_link); @@ -248,14 +248,14 @@ nm_device_factory_manager_for_each_factory(NMDeviceFactoryManagerFactoryFunc cal } static gboolean -_add_factory(NMDeviceFactory * factory, - const char * path, +_add_factory(NMDeviceFactory *factory, + const char *path, NMDeviceFactoryManagerFactoryFunc callback, gpointer user_data) { - const NMLinkType * link_types = NULL; + const NMLinkType *link_types = NULL; const char *const *setting_types = NULL; - GSList * list, *list2; + GSList *list, *list2; int i; g_return_val_if_fail(factories_by_link, FALSE); @@ -312,22 +312,22 @@ factories_list_unref(GSList *list) } static void -load_factories_from_dir(const char * dirname, +load_factories_from_dir(const char *dirname, NMDeviceFactoryManagerFactoryFunc callback, gpointer user_data) { NMDeviceFactory *factory; - GError * error = NULL; - char ** path, **paths; + GError *error = NULL; + char **path, **paths; paths = nm_utils_read_plugin_paths(dirname, PLUGIN_PREFIX); if (!paths) return; for (path = paths; *path; path++) { - GModule * plugin; + GModule *plugin; NMDeviceFactoryCreateFunc create_func; - const char * item; + const char *item; item = strrchr(*path, '/'); g_assert(item); diff --git a/src/core/devices/nm-device-factory.h b/src/core/devices/nm-device-factory.h index d9b50563..51d64767 100644 --- a/src/core/devices/nm-device-factory.h +++ b/src/core/devices/nm-device-factory.h @@ -45,8 +45,8 @@ typedef struct { * Returns the #NMLinkType and #NMSetting names that this plugin * supports. This function MUST be implemented. */ - void (*get_supported_types)(NMDeviceFactory * factory, - const NMLinkType ** out_link_types, + void (*get_supported_types)(NMDeviceFactory *factory, + const NMLinkType **out_link_types, const char *const **out_setting_types); /** @@ -91,8 +91,8 @@ typedef struct { * Returns: the interface name, or %NULL */ char *(*get_connection_iface)(NMDeviceFactory *factory, - NMConnection * connection, - const char * parent_iface); + NMConnection *connection, + const char *parent_iface); /** * create_device: @@ -112,11 +112,11 @@ typedef struct { * * Returns: the new unrealized #NMDevice, or %NULL */ - NMDevice *(*create_device)(NMDeviceFactory * factory, - const char * iface, + NMDevice *(*create_device)(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore); + NMConnection *connection, + gboolean *out_ignore); } NMDeviceFactoryClass; @@ -143,21 +143,21 @@ typedef NMDeviceFactory *(*NMDeviceFactoryCreateFunc)(GError **error); /*****************************************************************************/ const char *nm_device_factory_get_connection_parent(NMDeviceFactory *factory, - NMConnection * connection); + NMConnection *connection); char *nm_device_factory_get_connection_iface(NMDeviceFactory *factory, - NMConnection * connection, - const char * parent_iface, - GError ** error); + NMConnection *connection, + const char *parent_iface, + GError **error); void nm_device_factory_start(NMDeviceFactory *factory); -NMDevice *nm_device_factory_create_device(NMDeviceFactory * factory, - const char * iface, +NMDevice *nm_device_factory_create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore, - GError ** error); + NMConnection *connection, + gboolean *out_ignore, + GError **error); #define NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(...) \ { \ @@ -171,14 +171,14 @@ NMDevice *nm_device_factory_create_device(NMDeviceFactory * factory, } #define NM_DEVICE_FACTORY_DECLARE_TYPES(...) \ - static void get_supported_types(NMDeviceFactory * factory, \ - const NMLinkType ** out_link_types, \ + static void get_supported_types(NMDeviceFactory *factory, \ + const NMLinkType **out_link_types, \ const char *const **out_setting_types) \ { \ static NMLinkType const _link_types_null[1] = {NM_LINK_TYPE_NONE}; \ static const char *const _setting_types_null[1] = {NULL}; \ \ - const NMLinkType * _link_types = _link_types_null; \ + const NMLinkType *_link_types = _link_types_null; \ const char *const *_setting_types = _setting_types_null; \ \ { \ diff --git a/src/core/devices/nm-device-generic.c b/src/core/devices/nm-device-generic.c index 08ea5ac5..9f85925b 100644 --- a/src/core/devices/nm-device-generic.c +++ b/src/core/devices/nm-device-generic.c @@ -58,7 +58,7 @@ get_type_description(NMDevice *device) static void realize_start_notify(NMDevice *device, const NMPlatformLink *plink) { - NMDeviceGeneric * self = NM_DEVICE_GENERIC(device); + NMDeviceGeneric *self = NM_DEVICE_GENERIC(device); NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE(self); int ifindex; @@ -112,7 +112,7 @@ update_connection(NMDevice *device, NMConnection *connection) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceGeneric * self = NM_DEVICE_GENERIC(object); + NMDeviceGeneric *self = NM_DEVICE_GENERIC(object); NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE(self); switch (prop_id) { @@ -128,7 +128,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDeviceGeneric * self = NM_DEVICE_GENERIC(object); + NMDeviceGeneric *self = NM_DEVICE_GENERIC(object); NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE(self); switch (prop_id) { @@ -180,7 +180,7 @@ nm_device_generic_new(const NMPlatformLink *plink, gboolean nm_plugin_missing) static void dispose(GObject *object) { - NMDeviceGeneric * self = NM_DEVICE_GENERIC(object); + NMDeviceGeneric *self = NM_DEVICE_GENERIC(object); NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE(self); nm_clear_g_free(&priv->type_description); @@ -202,9 +202,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_generic = { static void nm_device_generic_class_init(NMDeviceGenericClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructor = constructor; object_class->dispose = dispose; diff --git a/src/core/devices/nm-device-infiniband.c b/src/core/devices/nm-device-infiniband.c index df14dfa8..aef61222 100644 --- a/src/core/devices/nm-device-infiniband.c +++ b/src/core/devices/nm-device-infiniband.c @@ -13,7 +13,6 @@ #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-act-request.h" -#include "nm-ip4-config.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" @@ -64,7 +63,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) nm_auto_close int dirfd = -1; NMSettingInfiniband *s_infiniband; char ifname_verified[IFNAMSIZ]; - const char * transport_mode; + const char *transport_mode; gboolean ok; s_infiniband = nm_device_get_applied_setting(device, NM_TYPE_SETTING_INFINIBAND); @@ -139,11 +138,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingInfiniband *s_infiniband; @@ -197,12 +196,12 @@ update_connection(NMDevice *device, NMConnection *connection) } static gboolean -can_reapply_change(NMDevice * device, +can_reapply_change(NMDevice *device, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { NMDeviceClass *device_class; @@ -219,14 +218,14 @@ can_reapply_change(NMDevice * device, } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE(device); - NMSettingInfiniband * s_infiniband; + NMSettingInfiniband *s_infiniband; int r; s_infiniband = nm_connection_get_setting_infiniband(connection); @@ -367,9 +366,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_infiniband = { static void nm_device_infiniband_class_init(NMDeviceInfinibandClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; object_class->set_property = set_property; @@ -410,11 +409,11 @@ nm_device_infiniband_class_init(NMDeviceInfinibandClass *klass) NMInfinibandDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { gboolean is_partition = FALSE; diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c index fe2e2023..02680dd7 100644 --- a/src/core/devices/nm-device-ip-tunnel.c +++ b/src/core/devices/nm-device-ip-tunnel.c @@ -22,7 +22,6 @@ #include "libnm-core-intern/nm-core-internal.h" #include "settings/nm-settings.h" #include "nm-act-request.h" -#include "nm-ip4-config.h" #define _NMLOG_DEVICE_TYPE NMDeviceIPTunnel #include "nm-device-logging.h" @@ -44,14 +43,14 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceIPTunnel, typedef struct { NMIPTunnelMode mode; - char * local; - char * remote; + char *local; + char *remote; guint8 ttl; guint8 tos; gboolean path_mtu_discovery; int addr_family; - char * input_key; - char * output_key; + char *input_key; + char *output_key; guint8 encap_limit; guint32 flow_label; NMIPTunnelFlags flags; @@ -153,7 +152,7 @@ address_set(int addr_family, char **p_addr, const NMIPAddr *addr_new) static void update_properties_from_ifindex(NMDevice *device, int ifindex) { - NMDeviceIPTunnel * self = NM_DEVICE_IP_TUNNEL(device); + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL(device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); int parent_ifindex = 0; NMIPAddr local = NM_IP_ADDR_INIT; @@ -164,7 +163,7 @@ update_properties_from_ifindex(NMDevice *device, int ifindex) gboolean pmtud = FALSE; guint32 flow_label = 0; NMIPTunnelFlags flags = NM_IP_TUNNEL_FLAG_NONE; - char * key; + char *key; if (ifindex <= 0) { clear: @@ -273,7 +272,7 @@ clear: NM_IP_TUNNEL_MODE_IP6GRE, NM_IP_TUNNEL_MODE_IP6GRETAP)) { const NMPlatformLnkIp6Tnl *lnk; - NMPlatform * plat = nm_device_get_platform(device); + NMPlatform *plat = nm_device_get_platform(device); if (priv->mode == NM_IP_TUNNEL_MODE_IP6GRE) lnk = nm_platform_link_get_lnk_ip6gre(plat, ifindex, NULL); @@ -384,11 +383,11 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingIPTunnel *s_ip_tunnel; @@ -417,9 +416,9 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceIPTunnel * self = NM_DEVICE_IP_TUNNEL(device); + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL(device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); - NMSettingIPTunnel * s_ip_tunnel = + NMSettingIPTunnel *s_ip_tunnel = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_IP_TUNNEL); if (nm_setting_ip_tunnel_get_mode(s_ip_tunnel) != priv->mode) @@ -491,10 +490,10 @@ update_connection(NMDevice *device, NMConnection *connection) static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceIPTunnel * self = NM_DEVICE_IP_TUNNEL(device); + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL(device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); - NMSettingIPTunnel * s_ip_tunnel; - const char * parent; + NMSettingIPTunnel *s_ip_tunnel; + const char *parent; if (!NM_DEVICE_CLASS(nm_device_ip_tunnel_parent_class) ->check_connection_compatible(device, connection, error)) @@ -643,23 +642,23 @@ tunnel_mode_to_link_type(NMIPTunnelMode tunnel_mode) /*****************************************************************************/ static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); - NMSettingIPTunnel * s_ip_tunnel; + const char *iface = nm_device_get_iface(device); + NMSettingIPTunnel *s_ip_tunnel; NMPlatformLnkGre lnk_gre = {}; NMPlatformLnkSit lnk_sit = {}; NMPlatformLnkIpIp lnk_ipip = {}; NMPlatformLnkIp6Tnl lnk_ip6tnl = {}; - const char * str; + const char *str; gint64 val; NMIPTunnelMode mode; int r; - gs_free char * hwaddr = NULL; + gs_free char *hwaddr = NULL; guint8 mac_address[ETH_ALEN]; gboolean mac_address_valid = FALSE; @@ -909,12 +908,12 @@ unrealize_notify(NMDevice *device) } static gboolean -can_reapply_change(NMDevice * device, +can_reapply_change(NMDevice *device, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { NMDeviceClass *device_class; @@ -934,7 +933,7 @@ can_reapply_change(NMDevice * device, static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceIPTunnel * self = NM_DEVICE_IP_TUNNEL(device); + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL(device); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); if (_nm_ip_tunnel_mode_is_layer2(priv->mode) @@ -1033,7 +1032,7 @@ constructed(GObject *object) static void dispose(GObject *object) { - NMDeviceIPTunnel * self = NM_DEVICE_IP_TUNNEL(object); + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL(object); NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self); nm_clear_g_free(&priv->local); @@ -1079,9 +1078,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_ip_tunnel = { static void nm_device_ip_tunnel_class_init(NMDeviceIPTunnelClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructed = constructed; object_class->dispose = dispose; @@ -1203,11 +1202,11 @@ nm_device_ip_tunnel_class_init(NMDeviceIPTunnelClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IP_TUNNEL_DEVICE_FACTORY, NMIPTunnelDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { NMSettingIPTunnel *s_ip_tunnel; NMIPTunnelMode mode; @@ -1256,7 +1255,7 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) static char * get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { - const char * ifname; + const char *ifname; NMSettingIPTunnel *s_ip_tunnel; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_IP_TUNNEL_SETTING_NAME), diff --git a/src/core/devices/nm-device-macsec.c b/src/core/devices/nm-device-macsec.c index 51b7225b..5cc0b8da 100644 --- a/src/core/devices/nm-device-macsec.c +++ b/src/core/devices/nm-device-macsec.c @@ -49,9 +49,9 @@ typedef struct { gulong parent_mtu_id; struct { - NMSupplicantManager * mgr; + NMSupplicantManager *mgr; NMSupplMgrCreateIfaceHandle *create_handle; - NMSupplicantInterface * iface; + NMSupplicantInterface *iface; gulong iface_state_id; @@ -92,7 +92,7 @@ static NM_UTILS_LOOKUP_STR_DEFINE(validation_mode_to_string, NM_UTILS_LOOKUP_STR_ITEM(2, "strict"), ); static void -parent_state_changed(NMDevice * parent, +parent_state_changed(NMDevice *parent, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason, @@ -126,7 +126,7 @@ parent_changed_notify(NMDevice *device, int new_ifindex, NMDevice *new_parent) { - NMDeviceMacsec * self = NM_DEVICE_MACSEC(device); + NMDeviceMacsec *self = NM_DEVICE_MACSEC(device); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); NM_DEVICE_CLASS(nm_device_macsec_parent_class) @@ -166,9 +166,9 @@ parent_changed_notify(NMDevice *device, static void update_properties(NMDevice *device) { - NMDeviceMacsec * self; - NMDeviceMacsecPrivate * priv; - const NMPlatformLink * plink = NULL; + NMDeviceMacsec *self; + NMDeviceMacsecPrivate *priv; + const NMPlatformLink *plink = NULL; const NMPlatformLnkMacsec *props = NULL; int ifindex; @@ -220,10 +220,10 @@ static NMSupplicantConfig * build_supplicant_config(NMDeviceMacsec *self, GError **error) { gs_unref_object NMSupplicantConfig *config = NULL; - NMSettingMacsec * s_macsec; - NMSetting8021x * s_8021x; - NMConnection * connection; - const char * con_uuid; + NMSettingMacsec *s_macsec; + NMSetting8021x *s_8021x; + NMConnection *connection; + const char *con_uuid; guint32 mtu; connection = nm_device_get_applied_connection(NM_DEVICE(self)); @@ -275,14 +275,14 @@ supplicant_interface_release(NMDeviceMacsec *self) } static void -macsec_secrets_cb(NMActRequest * req, +macsec_secrets_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * connection, - GError * error, + NMSettingsConnection *connection, + GError *error, gpointer user_data) { - NMDeviceMacsec * self = NM_DEVICE_MACSEC(user_data); - NMDevice * device = NM_DEVICE(self); + NMDeviceMacsec *self = NM_DEVICE_MACSEC(user_data); + NMDevice *device = NM_DEVICE(self); NMDeviceMacsecPrivate *priv; g_return_if_fail(NM_IS_DEVICE_MACSEC(self)); @@ -321,12 +321,12 @@ macsec_secrets_cancel(NMDeviceMacsec *self) } static void -macsec_secrets_get_secrets(NMDeviceMacsec * self, - const char * setting_name, +macsec_secrets_get_secrets(NMDeviceMacsec *self, + const char *setting_name, NMSecretAgentGetSecretsFlags flags) { NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); - NMActRequest * req; + NMActRequest *req; macsec_secrets_cancel(self); @@ -341,12 +341,12 @@ macsec_secrets_get_secrets(NMDeviceMacsec * self, static gboolean supplicant_lnk_timeout_cb(gpointer user_data) { - NMDeviceMacsec * self = NM_DEVICE_MACSEC(user_data); + NMDeviceMacsec *self = NM_DEVICE_MACSEC(user_data); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); - NMDevice * dev = NM_DEVICE(self); - NMActRequest * req; - NMConnection * applied_connection; - const char * setting_name; + NMDevice *dev = NM_DEVICE(self); + NMActRequest *req; + NMConnection *applied_connection; + const char *setting_name; priv->supplicant.lnk_timeout_id = 0; @@ -409,7 +409,7 @@ supplicant_iface_state_is_completed(NMDeviceMacsec *self, NMSupplicantInterfaceS */ if (nm_device_get_state(NM_DEVICE(self)) == NM_DEVICE_STATE_CONFIG) { _LOGI(LOGD_DEVICE, "Activation: Stage 2 of 5 (Device Configure) successful."); - nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self)); + nm_device_activate_schedule_stage3_ip_config(NM_DEVICE(self), FALSE); } return; } @@ -422,7 +422,7 @@ supplicant_iface_state_is_completed(NMDeviceMacsec *self, NMSupplicantInterfaceS static void supplicant_iface_assoc_cb(NMSupplicantInterface *iface, GError *error, gpointer user_data) { - NMDeviceMacsec * self; + NMDeviceMacsec *self; NMDeviceMacsecPrivate *priv; if (nm_utils_error_is_cancelled_or_disposing(error)) @@ -450,9 +450,9 @@ supplicant_iface_assoc_cb(NMSupplicantInterface *iface, GError *error, gpointer static gboolean supplicant_iface_start(NMDeviceMacsec *self) { - NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); + NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); gs_unref_object NMSupplicantConfig *config = NULL; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; config = build_supplicant_config(self, &error); if (!config) { @@ -476,8 +476,8 @@ supplicant_iface_state_cb(NMSupplicantInterface *iface, int disconnect_reason, gpointer user_data) { - NMDeviceMacsec * self = NM_DEVICE_MACSEC(user_data); - NMDeviceMacsecPrivate * priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); + NMDeviceMacsec *self = NM_DEVICE_MACSEC(user_data); + NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); NMSupplicantInterfaceState new_state = new_state_i; NMSupplicantInterfaceState old_state = old_state_i; @@ -506,7 +506,7 @@ supplicant_iface_state_cb(NMSupplicantInterface *iface, static gboolean handle_auth_or_fail(NMDeviceMacsec *self, NMActRequest *req, gboolean new_secrets) { - const char * setting_name; + const char *setting_name; NMConnection *applied_connection; if (!nm_device_auth_retries_try_next(NM_DEVICE(self))) @@ -536,11 +536,11 @@ handle_auth_or_fail(NMDeviceMacsec *self, NMActRequest *req, gboolean new_secret static gboolean supplicant_connection_timeout_cb(gpointer user_data) { - NMDeviceMacsec * self = NM_DEVICE_MACSEC(user_data); + NMDeviceMacsec *self = NM_DEVICE_MACSEC(user_data); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - NMActRequest * req; - NMSettingsConnection * connection; + NMDevice *device = NM_DEVICE(self); + NMActRequest *req; + NMSettingsConnection *connection; guint64 timestamp = 0; gboolean new_secrets = TRUE; @@ -585,13 +585,13 @@ supplicant_connection_timeout_cb(gpointer user_data) } static void -supplicant_interface_create_cb(NMSupplicantManager * supplicant_manager, +supplicant_interface_create_cb(NMSupplicantManager *supplicant_manager, NMSupplMgrCreateIfaceHandle *handle, - NMSupplicantInterface * iface, - GError * error, + NMSupplicantInterface *iface, + GError *error, gpointer user_data) { - NMDeviceMacsec * self; + NMDeviceMacsec *self; NMDeviceMacsecPrivate *priv; guint timeout; @@ -633,11 +633,11 @@ supplicant_interface_create_cb(NMSupplicantManager * supplicant_manager, static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceMacsec * self = NM_DEVICE_MACSEC(device); + NMDeviceMacsec *self = NM_DEVICE_MACSEC(device); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); - NMConnection * connection; - NMDevice * parent; - const char * setting_name; + NMConnection *connection; + NMDevice *parent; + const char *setting_name; int ifindex; connection = nm_device_get_applied_connection(NM_DEVICE(self)); @@ -712,17 +712,17 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); - NMSettingMacsec * s_macsec; + const char *iface = nm_device_get_iface(device); + NMSettingMacsec *s_macsec; NMPlatformLnkMacsec lnk = {}; int parent_ifindex; - const char * hw_addr; + const char *hw_addr; union { struct { guint8 mac[6]; @@ -789,7 +789,7 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) } static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) @@ -803,7 +803,7 @@ device_state_changed(NMDevice * device, static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceMacsec * self = NM_DEVICE_MACSEC(object); + NMDeviceMacsec *self = NM_DEVICE_MACSEC(object); NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE(self); switch (prop_id) { @@ -905,9 +905,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_macsec = { static void nm_device_macsec_class_init(NMDeviceMacsecClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; object_class->dispose = dispose; @@ -1015,11 +1015,11 @@ nm_device_macsec_class_init(NMDeviceMacsecClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_MACSEC_DEVICE_FACTORY, NMMacsecDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_MACSEC, NM_DEVICE_IFACE, @@ -1037,8 +1037,8 @@ static const char * get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) { NMSettingMacsec *s_macsec; - NMSettingWired * s_wired; - const char * parent = NULL; + NMSettingWired *s_wired; + const char *parent = NULL; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACSEC_SETTING_NAME), NULL); @@ -1061,7 +1061,7 @@ static char * get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { NMSettingMacsec *s_macsec; - const char * ifname; + const char *ifname; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACSEC_SETTING_NAME), NULL); diff --git a/src/core/devices/nm-device-macvlan.c b/src/core/devices/nm-device-macvlan.c index 937ba9e4..40ecc5fd 100644 --- a/src/core/devices/nm-device-macvlan.c +++ b/src/core/devices/nm-device-macvlan.c @@ -19,7 +19,6 @@ #include "nm-setting-macvlan.h" #include "nm-setting-wired.h" #include "nm-active-connection.h" -#include "nm-ip4-config.h" #include "nm-utils.h" #define _NMLOG_DEVICE_TYPE NMDeviceMacvlan @@ -104,7 +103,7 @@ platform_mode_to_string(guint mode) /*****************************************************************************/ static void -parent_state_changed(NMDevice * parent, +parent_state_changed(NMDevice *parent, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason, @@ -138,7 +137,7 @@ parent_changed_notify(NMDevice *device, int new_ifindex, NMDevice *new_parent) { - NMDeviceMacvlan * self = NM_DEVICE_MACVLAN(device); + NMDeviceMacvlan *self = NM_DEVICE_MACVLAN(device); NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE(self); NM_DEVICE_CLASS(nm_device_macvlan_parent_class) @@ -178,11 +177,11 @@ parent_changed_notify(NMDevice *device, static void update_properties(NMDevice *device) { - NMDeviceMacvlan * self = NM_DEVICE_MACVLAN(device); - NMDeviceMacvlanPrivate * priv = NM_DEVICE_MACVLAN_GET_PRIVATE(self); - GObject * object = G_OBJECT(device); + NMDeviceMacvlan *self = NM_DEVICE_MACVLAN(device); + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE(self); + GObject *object = G_OBJECT(device); const NMPlatformLnkMacvlan *props; - const NMPlatformLink * plink; + const NMPlatformLink *plink; if (priv->props.tap) props = nm_platform_link_get_lnk_macvtap(nm_device_get_platform(device), @@ -228,14 +227,14 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); - NMSettingMacvlan * s_macvlan; + const char *iface = nm_device_get_iface(device); + NMSettingMacvlan *s_macvlan; NMPlatformLnkMacvlan lnk = {}; int parent_ifindex; int r; @@ -312,8 +311,8 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE(device); - NMSettingMacvlan * s_macvlan; - const char * parent = NULL; + NMSettingMacvlan *s_macvlan; + const char *parent = NULL; if (!NM_DEVICE_CLASS(nm_device_macvlan_parent_class) ->check_connection_compatible(device, connection, error)) @@ -374,11 +373,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingMacvlan *s_macvlan; @@ -421,7 +420,7 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE(device); - NMSettingMacvlan * s_macvlan = + NMSettingMacvlan *s_macvlan = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_MACVLAN); int new_mode; @@ -511,9 +510,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_macvlan = { static void nm_device_macvlan_class_init(NMDeviceMacvlanClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); #if NM_MORE_ASSERTS object_class->dispose = dispose; @@ -570,11 +569,11 @@ nm_device_macvlan_class_init(NMDeviceMacvlanClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_MACVLAN_DEVICE_FACTORY, NMMacvlanDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { NMSettingMacvlan *s_macvlan; NMLinkType link_type; @@ -609,8 +608,8 @@ static const char * get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) { NMSettingMacvlan *s_macvlan; - NMSettingWired * s_wired; - const char * parent = NULL; + NMSettingWired *s_wired; + const char *parent = NULL; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACVLAN_SETTING_NAME), NULL); @@ -633,7 +632,7 @@ static char * get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { NMSettingMacvlan *s_macvlan; - const char * ifname; + const char *ifname; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACVLAN_SETTING_NAME), NULL); diff --git a/src/core/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c index 04051bec..5ff32401 100644 --- a/src/core/devices/nm-device-ppp.c +++ b/src/core/devices/nm-device-ppp.c @@ -7,16 +7,14 @@ #include "nm-device-ppp.h" -#include "nm-ip4-config.h" +#include "nm-l3-config-data.h" #include "nm-act-request.h" #include "nm-device-factory.h" #include "nm-device-private.h" #include "nm-manager.h" #include "nm-setting-pppoe.h" #include "libnm-platform/nm-platform.h" -#include "ppp/nm-ppp-manager.h" -#include "ppp/nm-ppp-manager-call.h" -#include "ppp/nm-ppp-status.h" +#include "ppp/nm-ppp-mgr.h" #define _NMLOG_DEVICE_TYPE NMDevicePpp #include "nm-device-logging.h" @@ -24,8 +22,7 @@ /*****************************************************************************/ typedef struct _NMDevicePppPrivate { - NMPPPManager *ppp_manager; - NMIP4Config * ip4_config; + NMPppMgr *ppp_mgr; } NMDevicePppPrivate; struct _NMDevicePpp { @@ -42,86 +39,92 @@ G_DEFINE_TYPE(NMDevicePpp, nm_device_ppp, NM_TYPE_DEVICE) #define NM_DEVICE_PPP_GET_PRIVATE(self) \ _NM_GET_PRIVATE(self, NMDevicePpp, NM_IS_DEVICE_PPP, NMDevice) +/*****************************************************************************/ + static NMDeviceCapabilities get_generic_capabilities(NMDevice *device) { return NM_DEVICE_CAP_IS_SOFTWARE; } +/*****************************************************************************/ + static void -ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +_ppp_mgr_cleanup(NMDevicePpp *self) { - NMDevice *device = NM_DEVICE(user_data); - - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } + NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + + nm_clear_pointer(&priv->ppp_mgr, nm_ppp_mgr_destroy); } static void -ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data) +_ppp_mgr_stage3_maybe_ready(NMDevicePpp *self) { - NMDevice * device = NM_DEVICE(user_data); - NMDevicePpp * self = NM_DEVICE_PPP(device); - gs_free char *old_name = NULL; - gs_free_error GError *error = NULL; - - if (!nm_device_take_over_link(device, ifindex, &old_name, &error)) { - _LOGW(LOGD_DEVICE | LOGD_PPP, - "could not take control of link %d: %s", - ifindex, - error->message); - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } + NMDevice *device = NM_DEVICE(self); + NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + int IS_IPv4; + + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; + const NMPppMgrIPData *ip_data; - if (old_name) - nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP); + ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_mgr, addr_family); + if (ip_data->ip_received) + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, ip_data->l3cd); + } - nm_device_activate_schedule_stage3_ip_config_start(device); + if (nm_ppp_mgr_get_state(priv->ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG) + nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_READY, NULL); } static void -_ppp_ip4_config_handle(NMDevicePpp *self) +_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data) { - NMDevice * device = NM_DEVICE(self); - NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + NMDevicePpp *self = NM_DEVICE_PPP(user_data); + NMDevice *device = NM_DEVICE(self); + NMDeviceState device_state; - if (!priv->ip4_config) + if (callback_data->callback_type != NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED) return; - if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG - && nm_device_activate_ip4_state_in_conf(device)) { - nm_device_activate_schedule_ip_config_result( - device, - AF_INET, - NM_IP_CONFIG_CAST(g_steal_pointer(&priv->ip4_config))); + device_state = nm_device_get_state(device); + + if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) { + if (device_state <= NM_DEVICE_STATE_ACTIVATED) + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, callback_data->data.reason); return; } -} -static void -ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) -{ - NMDevicePpp * self = NM_DEVICE_PPP(user_data); - NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + if (device_state < NM_DEVICE_STATE_IP_CONFIG) { + if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) { + gs_free char *old_name = NULL; + gs_free_error GError *error = NULL; + + if (!nm_device_take_over_link(device, callback_data->data.ifindex, &old_name, &error)) { + _LOGW(LOGD_DEVICE | LOGD_PPP, + "could not take control of link %d: %s", + callback_data->data.ifindex, + error->message); + _ppp_mgr_cleanup(self); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; + } + + if (old_name) + nm_manager_remove_device(NM_MANAGER_GET, old_name, NM_DEVICE_TYPE_PPP); + + nm_device_activate_schedule_stage2_device_config(device, FALSE); + } + return; + } - _LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd"); - nm_g_object_ref_set(&priv->ip4_config, config); - _ppp_ip4_config_handle(self); + _ppp_mgr_stage3_maybe_ready(self); } +/*****************************************************************************/ + static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { @@ -145,97 +148,92 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDevicePpp * self = NM_DEVICE_PPP(device); + NMDevicePpp *self = NM_DEVICE_PPP(device); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); - NMSettingPppoe * s_pppoe; - NMActRequest * req; - GError * error = NULL; + NMSettingPppoe *s_pppoe; + NMActRequest *req; + + if (!priv->ppp_mgr) { + gs_free_error GError *error = NULL; + + req = nm_device_get_act_request(device); + g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); + + s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE); + g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); + + priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){ + .netns = nm_device_get_netns(device), + .parent_iface = nm_setting_pppoe_get_parent(s_pppoe), + .callback = _ppp_mgr_callback, + .user_data = self, + .act_req = req, + .ppp_username = nm_setting_pppoe_get_username(s_pppoe), + .timeout_secs = 30, + .baud_override = 0, + }), + &error); + if (!priv->ppp_mgr) { + _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message); + *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } - req = nm_device_get_act_request(device); - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); + return NM_ACT_STAGE_RETURN_POSTPONE; + } - s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE); - g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); + if (nm_ppp_mgr_get_state(priv->ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX) + return NM_ACT_STAGE_RETURN_POSTPONE; - g_clear_object(&priv->ip4_config); + return NM_ACT_STAGE_RETURN_SUCCESS; +} - priv->ppp_manager = nm_ppp_manager_create(nm_setting_pppoe_get_parent(s_pppoe), &error); +static void +act_stage3_ip_config(NMDevice *device, int addr_family) +{ + NMDevicePpp *self = NM_DEVICE_PPP(device); + NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + NMPppMgrState ppp_state; - if (priv->ppp_manager) { - nm_ppp_manager_set_route_parameters(priv->ppp_manager, - nm_device_get_route_table(device, AF_INET), - nm_device_get_route_metric(device, AF_INET), - nm_device_get_route_table(device, AF_INET6), - nm_device_get_route_metric(device, AF_INET6)); + if (!priv->ppp_mgr) { + nm_assert_not_reached(); + return; } - if (!priv->ppp_manager - || !nm_ppp_manager_start(priv->ppp_manager, - req, - nm_setting_pppoe_get_username(s_pppoe), - 30, - 0, - &error)) { - _LOGW(LOGD_DEVICE | LOGD_PPP, "PPPoE failed to start: %s", error->message); - g_error_free(error); + ppp_state = nm_ppp_mgr_get_state(priv->ppp_mgr); - g_clear_object(&priv->ppp_manager); + nm_assert(NM_IN_SET(ppp_state, NM_PPP_MGR_STATE_HAVE_IFINDEX, NM_PPP_MGR_STATE_HAVE_IP_CONFIG)); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; + if (ppp_state < NM_PPP_MGR_STATE_HAVE_IP_CONFIG) { + nm_device_devip_set_state(device, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING, NULL); + return; } - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, - G_CALLBACK(ppp_state_changed), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK(ppp_ifindex_set), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, - G_CALLBACK(ppp_ip4_config), - self); - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static gboolean -_schedule_ip_config_result(gpointer user_data) -{ - gs_unref_object NMDevicePpp *self = user_data; - - _ppp_ip4_config_handle(self); - return G_SOURCE_REMOVE; + _ppp_mgr_stage3_maybe_ready(self); } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static const char * +get_ip_method_auto(NMDevice *device, int addr_family) { - if (addr_family == AF_INET) { - NMDevicePpp * self = NM_DEVICE_PPP(device); - NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); - - if (priv->ip4_config) - nm_g_idle_add(_schedule_ip_config_result, g_object_ref(self)); - - /* Wait IPCP termination */ - return NM_ACT_STAGE_RETURN_POSTPONE; + if (NM_IS_IPv4(addr_family)) { + /* We cannot do DHCPv4 on a PPP link, instead we get "auto" IP addresses + * by pppd. Return "manual" here, which has the suitable effect to a + * (zero) manual addresses in addition. */ + return NM_SETTING_IP6_CONFIG_METHOD_MANUAL; } - return NM_DEVICE_CLASS(nm_device_ppp_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + /* We can do autoconf6 on an PPP link, but we should already get an IPv6 + * address from pppd. Use that instead. We however do want to generate our + * (own) IPv6 link local address, so return "link-local". */ + return NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL; } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { int parent_ifindex; @@ -260,17 +258,13 @@ create_and_realize(NMDevice * device, static void deactivate(NMDevice *device) { - NMDevicePpp * self = NM_DEVICE_PPP(device); - NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + NMDevicePpp *self = NM_DEVICE_PPP(device); - if (priv->ppp_manager) { - nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL); - g_clear_object(&priv->ppp_manager); - } - - g_clear_object(&priv->ip4_config); + _ppp_mgr_cleanup(self); } +/*****************************************************************************/ + static void nm_device_ppp_init(NMDevicePpp *self) {} @@ -278,10 +272,9 @@ nm_device_ppp_init(NMDevicePpp *self) static void dispose(GObject *object) { - NMDevicePpp * self = NM_DEVICE_PPP(object); - NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self); + NMDevicePpp *self = NM_DEVICE_PPP(object); - g_clear_object(&priv->ip4_config); + _ppp_mgr_cleanup(self); G_OBJECT_CLASS(nm_device_ppp_parent_class)->dispose(object); } @@ -293,9 +286,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_ppp = { static void nm_device_ppp_class_init(NMDevicePppClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->dispose = dispose; @@ -306,7 +299,8 @@ nm_device_ppp_class_init(NMDevicePppClass *klass) device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_PPP); device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->get_ip_method_auto = get_ip_method_auto; device_class->check_connection_compatible = check_connection_compatible; device_class->create_and_realize = create_and_realize; device_class->deactivate = deactivate; @@ -320,11 +314,11 @@ nm_device_ppp_class_init(NMDevicePppClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_PPP_DEVICE_FACTORY, NMPppDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_PPP, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h index b55e8b43..790bb823 100644 --- a/src/core/devices/nm-device-private.h +++ b/src/core/devices/nm-device-private.h @@ -8,6 +8,7 @@ #define __NETWORKMANAGER_DEVICE_PRIVATE_H__ #include "nm-device.h" +#include "nm-l3-config-data.h" /* This file should only be used by subclasses of NMDevice */ @@ -21,12 +22,6 @@ enum NMActStageReturn { NM_ACT_STAGE_RETURN_FAILURE = 0, /* Hard failure of activation */ NM_ACT_STAGE_RETURN_SUCCESS, /* Activation stage done */ NM_ACT_STAGE_RETURN_POSTPONE, /* Long-running operation in progress */ - NM_ACT_STAGE_RETURN_IP_WAIT, /* IP config stage is waiting (state IP_WAIT) */ - NM_ACT_STAGE_RETURN_IP_DONE, /* IP config stage is done (state IP_DONE), - * For the ip-config stage, this is similar to - * NM_ACT_STAGE_RETURN_SUCCESS, except that no - * IP config should be committed. */ - NM_ACT_STAGE_RETURN_IP_FAIL, /* IP config stage failed (state IP_FAIL), activation may proceed */ }; #define NM_DEVICE_CAP_NONSTANDARD_CARRIER 0x80000000 @@ -34,8 +29,6 @@ enum NMActStageReturn { #define NM_DEVICE_CAP_INTERNAL_MASK 0xc0000000 -void nm_device_arp_announce(NMDevice *self); - NMSettings *nm_device_get_settings(NMDevice *self); NMManager *nm_device_get_manager(NMDevice *self); @@ -44,17 +37,13 @@ gboolean nm_device_set_ip_ifindex(NMDevice *self, int ifindex); gboolean nm_device_set_ip_iface(NMDevice *self, const char *iface); -void nm_device_activate_schedule_stage3_ip_config_start(NMDevice *device); - -gboolean nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family); - gboolean nm_device_bring_up(NMDevice *self, gboolean wait, gboolean *no_firmware); void nm_device_take_down(NMDevice *self, gboolean block); gboolean nm_device_take_over_link(NMDevice *self, int ifindex, char **old_name, GError **error); -gboolean nm_device_hw_addr_set(NMDevice * device, +gboolean nm_device_hw_addr_set(NMDevice *device, const char *addr, const char *detail, gboolean set_permanent); @@ -65,52 +54,7 @@ void nm_device_set_firmware_missing(NMDevice *self, gboolean missing); void nm_device_activate_schedule_stage1_device_prepare(NMDevice *device, gboolean do_sync); void nm_device_activate_schedule_stage2_device_config(NMDevice *device, gboolean do_sync); - -void -nm_device_activate_schedule_ip_config_result(NMDevice *device, int addr_family, NMIPConfig *config); - -void nm_device_activate_schedule_ip_config_timeout(NMDevice *device, int addr_family); - -NMDeviceIPState nm_device_activate_get_ip_state(NMDevice *self, int addr_family); - -static inline gboolean -nm_device_activate_ip4_state_in_conf(NMDevice *self) -{ - return nm_device_activate_get_ip_state(self, AF_INET) == NM_DEVICE_IP_STATE_CONF; -} - -static inline gboolean -nm_device_activate_ip4_state_in_wait(NMDevice *self) -{ - return nm_device_activate_get_ip_state(self, AF_INET) == NM_DEVICE_IP_STATE_WAIT; -} - -static inline gboolean -nm_device_activate_ip4_state_done(NMDevice *self) -{ - return nm_device_activate_get_ip_state(self, AF_INET) == NM_DEVICE_IP_STATE_DONE; -} - -static inline gboolean -nm_device_activate_ip6_state_in_conf(NMDevice *self) -{ - return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_CONF; -} - -static inline gboolean -nm_device_activate_ip6_state_in_wait(NMDevice *self) -{ - return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_WAIT; -} - -static inline gboolean -nm_device_activate_ip6_state_done(NMDevice *self) -{ - return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_DONE; -} - -gboolean nm_device_dhcp4_renew(NMDevice *device, gboolean release); -gboolean nm_device_dhcp6_renew(NMDevice *device, gboolean release); +void nm_device_activate_schedule_stage3_ip_config(NMDevice *device, gboolean do_sync); void nm_device_recheck_available_connections(NMDevice *device); @@ -122,46 +66,75 @@ void nm_device_master_release_slaves(NMDevice *self); void nm_device_set_carrier(NMDevice *self, gboolean carrier); void nm_device_queue_recheck_assume(NMDevice *device); -void nm_device_queue_recheck_available(NMDevice * device, +void nm_device_queue_recheck_available(NMDevice *device, NMDeviceStateReason available_reason, NMDeviceStateReason unavailable_reason); -void nm_device_set_dev2_ip_config(NMDevice *device, int addr_family, NMIPConfig *config); - gboolean nm_device_hw_addr_is_explict(NMDevice *device); -void nm_device_ip_method_failed(NMDevice *self, int addr_family, NMDeviceStateReason reason); +NMDeviceIPState nm_device_devip_get_state(NMDevice *self, int addr_family); -gboolean nm_device_sysctl_ip_conf_set(NMDevice * self, +void nm_device_devip_set_state_full(NMDevice *self, + int addr_family, + NMDeviceIPState ip_state, + const NML3ConfigData *l3cd, + NMDeviceStateReason failed_reason); + +static inline void +nm_device_devip_set_state(NMDevice *self, + int addr_family, + NMDeviceIPState ip_state, + const NML3ConfigData *l3cd) +{ + nm_assert(NM_IS_DEVICE(self)); + nm_assert_addr_family_or_unspec(addr_family); + nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd)); + nm_assert(NM_IN_SET(ip_state, NM_DEVICE_IP_STATE_PENDING, NM_DEVICE_IP_STATE_READY)); + + nm_device_devip_set_state_full(self, addr_family, ip_state, l3cd, NM_DEVICE_STATE_REASON_NONE); +} + +static inline void +nm_device_devip_set_failed(NMDevice *self, int addr_family, NMDeviceStateReason reason) +{ + nm_assert(NM_IS_DEVICE(self)); + nm_assert_addr_family_or_unspec(addr_family); + nm_assert(reason != NM_DEVICE_STATE_REASON_NONE); + + nm_device_devip_set_state_full(self, addr_family, NM_DEVICE_IP_STATE_FAILED, NULL, reason); +} + +gboolean nm_device_sysctl_ip_conf_set(NMDevice *self, int addr_family, const char *property, const char *value); -NMIP4Config *nm_device_ip4_config_new(NMDevice *self); +NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source); -NMIP6Config *nm_device_ip6_config_new(NMDevice *self); +const NML3ConfigData *nm_device_create_l3_config_data_from_connection(NMDevice *self, + NMConnection *connection); -NMIPConfig *nm_device_ip_config_new(NMDevice *self, int addr_family); +void nm_device_ip_method_dhcp4_start(NMDevice *self); -NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source); +void nm_device_ip_method_autoconf6_start(NMDevice *self); /*****************************************************************************/ -gint64 nm_device_get_configured_mtu_from_connection_default(NMDevice * self, +gint64 nm_device_get_configured_mtu_from_connection_default(NMDevice *self, const char *property_name, guint32 max_mtu); -guint32 nm_device_get_configured_mtu_from_connection(NMDevice * device, +guint32 nm_device_get_configured_mtu_from_connection(NMDevice *device, GType setting_type, NMDeviceMtuSource *out_source); -guint32 nm_device_get_configured_mtu_for_wired(NMDevice * self, +guint32 nm_device_get_configured_mtu_for_wired(NMDevice *self, NMDeviceMtuSource *out_source, - gboolean * out_force); + gboolean *out_force); -guint32 nm_device_get_configured_mtu_wired_parent(NMDevice * self, +guint32 nm_device_get_configured_mtu_wired_parent(NMDevice *self, NMDeviceMtuSource *out_source, - gboolean * out_force); + gboolean *out_force); void nm_device_commit_mtu(NMDevice *self); @@ -177,26 +150,26 @@ void nm_device_commit_mtu(NMDevice *self); _types; \ })) -gboolean _nm_device_hash_check_invalid_keys(GHashTable * hash, - const char * setting_name, - GError ** error, +gboolean _nm_device_hash_check_invalid_keys(GHashTable *hash, + const char *setting_name, + GError **error, const char *const *whitelist); #define nm_device_hash_check_invalid_keys(hash, setting_name, error, ...) \ _nm_device_hash_check_invalid_keys(hash, setting_name, error, NM_MAKE_STRV(__VA_ARGS__)) gboolean nm_device_match_parent(NMDevice *device, const char *parent); -gboolean nm_device_match_parent_hwaddr(NMDevice * device, +gboolean nm_device_match_parent_hwaddr(NMDevice *device, NMConnection *connection, gboolean fail_if_no_hwaddr); /*****************************************************************************/ -void nm_device_auth_request(NMDevice * self, - GDBusMethodInvocation * context, - NMConnection * connection, - const char * permission, +void nm_device_auth_request(NMDevice *self, + GDBusMethodInvocation *context, + NMConnection *connection, + const char *permission, gboolean allow_interaction, - GCancellable * cancellable, + GCancellable *cancellable, NMManagerDeviceAuthRequestFunc callback, gpointer user_data); diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index 0ab08f65..b6c4f88b 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -13,7 +13,6 @@ #include "nm-act-request.h" #include "nm-device-private.h" -#include "nm-ip4-config.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-tun.h" @@ -56,7 +55,7 @@ G_DEFINE_TYPE(NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE) static void update_properties_from_struct(NMDeviceTun *self, const NMPlatformLnkTun *props) { - NMDeviceTunPrivate * priv = NM_DEVICE_TUN_GET_PRIVATE(self); + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE(self); const NMPlatformLnkTun props0 = {}; if (!props) { @@ -129,11 +128,11 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingTun *s_tun; @@ -162,12 +161,12 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceTun * self = NM_DEVICE_TUN(device); + NMDeviceTun *self = NM_DEVICE_TUN(device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE(self); - NMSettingTun * s_tun; + NMSettingTun *s_tun; NMSettingTunMode mode; char s_buf[100]; - const char * str; + const char *str; /* Note: since we read tun properties from sysctl for older kernels, * we don't get proper change notifications. Make sure that all our @@ -217,15 +216,15 @@ update_connection(NMDevice *device, NMConnection *connection) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); + const char *iface = nm_device_get_iface(device); NMPlatformLnkTun props = {}; - NMSettingTun * s_tun; + NMSettingTun *s_tun; gint64 owner; gint64 group; int r; @@ -287,10 +286,10 @@ _same_og(const char *str, gboolean og_valid, guint32 og_num) static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceTun * self = NM_DEVICE_TUN(device); + NMDeviceTun *self = NM_DEVICE_TUN(device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE(self); NMSettingTunMode mode; - NMSettingTun * s_tun; + NMSettingTun *s_tun; if (!NM_DEVICE_CLASS(nm_device_tun_parent_class) ->check_connection_compatible(device, connection, error)) @@ -361,7 +360,7 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceTun * self = NM_DEVICE_TUN(device); + NMDeviceTun *self = NM_DEVICE_TUN(device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE(self); if (priv->props.type == IFF_TUN) { @@ -390,9 +389,9 @@ unrealize_notify(NMDevice *device) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceTun * self = NM_DEVICE_TUN(object); + NMDeviceTun *self = NM_DEVICE_TUN(object); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE(self); - const char * s; + const char *s; switch (prop_id) { case PROP_OWNER: @@ -458,9 +457,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_tun = { static void nm_device_tun_class_init(NMDeviceTunClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; @@ -531,11 +530,11 @@ nm_device_tun_class_init(NMDeviceTunClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_TUN_DEVICE_FACTORY, NMTunDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { g_return_val_if_fail(!plink || plink->type == NM_LINK_TYPE_TUN, NULL); g_return_val_if_fail(!connection diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c index 2a6ab04e..170922eb 100644 --- a/src/core/devices/nm-device-utils.c +++ b/src/core/devices/nm-device-utils.c @@ -151,10 +151,9 @@ NM_UTILS_LOOKUP_STR_DEFINE(nm_device_ip_state_to_string, NMDeviceIPState, NM_UTILS_LOOKUP_DEFAULT_WARN("unknown"), NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_NONE, "none"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_WAIT, "wait"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_CONF, "conf"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_DONE, "done"), - NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_FAIL, "fail"), ); + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_PENDING, "pending"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_READY, "done"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_IP_STATE_FAILED, "fail"), ); /*****************************************************************************/ @@ -166,7 +165,7 @@ typedef struct { int addr_family; NMIPAddr address; gulong cancellable_id; - GTask * task; + GTask *task; NMDnsSystemdResolvedResolveHandle *resolved_handle; } ResolveAddrInfo; @@ -219,9 +218,9 @@ resolve_addr_complete(ResolveAddrInfo *info, char *hostname_take, GError *error_ static void resolve_addr_helper_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - ResolveAddrInfo *info = user_data; + ResolveAddrInfo *info = user_data; gs_free_error GError *error = NULL; - gs_free char * output = NULL; + gs_free char *output = NULL; output = nm_utils_spawn_helper_finish(result, &error); if (nm_utils_error_is_cancelled(error)) @@ -246,12 +245,12 @@ resolve_addr_spawn_helper(ResolveAddrInfo *info) } static void -resolve_addr_resolved_cb(NMDnsSystemdResolved * resolved, - NMDnsSystemdResolvedResolveHandle * handle, +resolve_addr_resolved_cb(NMDnsSystemdResolved *resolved, + NMDnsSystemdResolvedResolveHandle *handle, const NMDnsSystemdResolvedAddressResult *names, guint names_len, guint64 flags, - GError * error, + GError *error, gpointer user_data) { ResolveAddrInfo *info = user_data; @@ -301,7 +300,7 @@ static void resolve_addr_cancelled(GObject *object, gpointer user_data) { ResolveAddrInfo *info = user_data; - GError * error = NULL; + GError *error = NULL; nm_clear_g_signal_handler(g_task_get_cancellable(info->task), &info->cancellable_id); nm_clear_pointer(&info->resolved_handle, nm_dns_systemd_resolved_resolve_cancel); @@ -312,11 +311,11 @@ resolve_addr_cancelled(GObject *object, gpointer user_data) void nm_device_resolve_address(int addr_family, gconstpointer address, - GCancellable * cancellable, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer cb_data) { - ResolveAddrInfo * info; + ResolveAddrInfo *info; NMDnsSystemdResolved *resolved; info = g_new(ResolveAddrInfo, 1); diff --git a/src/core/devices/nm-device-utils.h b/src/core/devices/nm-device-utils.h index 7200b0ea..7b879c90 100644 --- a/src/core/devices/nm-device-utils.h +++ b/src/core/devices/nm-device-utils.h @@ -73,23 +73,20 @@ const char *nm_device_sys_iface_state_to_string(NMDeviceSysIfaceState sys_iface_ /*****************************************************************************/ -typedef enum { +typedef enum _nm_packed { NM_DEVICE_IP_STATE_NONE, - NM_DEVICE_IP_STATE_WAIT, - NM_DEVICE_IP_STATE_CONF, - NM_DEVICE_IP_STATE_DONE, - NM_DEVICE_IP_STATE_FAIL, + NM_DEVICE_IP_STATE_PENDING, + NM_DEVICE_IP_STATE_READY, + NM_DEVICE_IP_STATE_FAILED, } NMDeviceIPState; const char *nm_device_ip_state_to_string(NMDeviceIPState ip_state); /*****************************************************************************/ -/*****************************************************************************/ - void nm_device_resolve_address(int addr_family, gconstpointer address, - GCancellable * cancellable, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer cb_data); diff --git a/src/core/devices/nm-device-veth.c b/src/core/devices/nm-device-veth.c index 28831b75..8c95a293 100644 --- a/src/core/devices/nm-device-veth.c +++ b/src/core/devices/nm-device-veth.c @@ -75,13 +75,13 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); + const char *iface = nm_device_get_iface(device); NMSettingVeth *s_veth; int r; @@ -143,7 +143,7 @@ static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMDeviceVeth *self = NM_DEVICE_VETH(object); - NMDevice * peer; + NMDevice *peer; switch (prop_id) { case PROP_PEER: @@ -168,9 +168,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_veth = { static void nm_device_veth_class_init(NMDeviceVethClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; @@ -201,11 +201,11 @@ nm_device_veth_class_init(NMDeviceVethClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VETH_DEVICE_FACTORY, NMVethDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_VETH, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c index d1e57411..0c101c70 100644 --- a/src/core/devices/nm-device-vlan.c +++ b/src/core/devices/nm-device-vlan.c @@ -15,7 +15,6 @@ #include "nm-device-private.h" #include "settings/nm-settings.h" #include "nm-act-request.h" -#include "nm-ip4-config.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-manager.h" @@ -55,7 +54,7 @@ G_DEFINE_TYPE(NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE) /*****************************************************************************/ static void -parent_state_changed(NMDevice * parent, +parent_state_changed(NMDevice *parent, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason, @@ -85,11 +84,11 @@ parent_mtu_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_data static void parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceVlan * self = NM_DEVICE_VLAN(device); - NMConnection * connection; - const char * new_mac, *old_mac; - NMSettingIPConfig *s_ip6; + NMDevice *device = NM_DEVICE(user_data); + NMDeviceVlan *self = NM_DEVICE_VLAN(device); + NMConnection *connection; + const char *old_mac; + const char *new_mac; /* Never touch assumed devices */ if (nm_device_sys_iface_state_is_external_or_assume(device)) @@ -113,13 +112,10 @@ parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_d NM_PRINT_FMT_QUOTE_STRING(new_mac)); if (new_mac) { nm_device_hw_addr_set(device, new_mac, "vlan-parent", TRUE); - nm_device_arp_announce(device); /* When changing the hw address the interface is taken down, * removing the IPv6 configuration; reapply it. */ - s_ip6 = nm_connection_get_setting_ip6_config(connection); - if (s_ip6) - nm_device_reactivate_ip_config(device, AF_INET6, s_ip6, s_ip6); + nm_device_l3cfg_commit(device, NM_L3_CFG_COMMIT_TYPE_UPDATE, FALSE); } } @@ -130,7 +126,7 @@ parent_changed_notify(NMDevice *device, int new_ifindex, NMDevice *new_parent) { - NMDeviceVlan * self = NM_DEVICE_VLAN(device); + NMDeviceVlan *self = NM_DEVICE_VLAN(device); NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE(self); NM_DEVICE_CLASS(nm_device_vlan_parent_class) @@ -179,8 +175,8 @@ parent_changed_notify(NMDevice *device, static void update_properties(NMDevice *device) { - NMDeviceVlanPrivate * priv; - const NMPlatformLink * plink = NULL; + NMDeviceVlanPrivate *priv; + const NMPlatformLink *plink = NULL; const NMPlatformLnkVlan *plnk = NULL; int ifindex; int parent_ifindex = 0; @@ -219,15 +215,15 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE(device); - const char * iface = nm_device_get_iface(device); - NMSettingVlan * s_vlan; + const char *iface = nm_device_get_iface(device); + NMSettingVlan *s_vlan; int parent_ifindex; guint vlan_id; int r; @@ -295,7 +291,7 @@ create_and_realize(NMDevice * device, static void unrealize_notify(NMDevice *device) { - NMDeviceVlan * self = NM_DEVICE_VLAN(device); + NMDeviceVlan *self = NM_DEVICE_VLAN(device); NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE(self); NM_DEVICE_CLASS(nm_device_vlan_parent_class)->unrealize_notify(device); @@ -331,8 +327,8 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE(device); - NMSettingVlan * s_vlan; - const char * parent; + NMSettingVlan *s_vlan; + const char *parent; if (!NM_DEVICE_CLASS(nm_device_vlan_parent_class) ->check_connection_compatible(device, connection, error)) @@ -372,11 +368,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, +check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { if (!nm_device_is_real(device)) return TRUE; @@ -386,11 +382,11 @@ check_connection_available(NMDevice * device, } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingVlan *s_vlan; @@ -432,11 +428,11 @@ complete_connection(NMDevice * device, static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceVlanPrivate * priv = NM_DEVICE_VLAN_GET_PRIVATE(device); - NMSettingVlan * s_vlan = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VLAN); + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE(device); + NMSettingVlan *s_vlan = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VLAN); int ifindex = nm_device_get_ifindex(device); const NMPlatformLink *plink; - const NMPObject * polnk; + const NMPObject *polnk; guint vlan_id; _NMVlanFlags vlan_flags; @@ -482,7 +478,7 @@ update_connection(NMDevice *device, NMConnection *connection) static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDevice * parent_device; + NMDevice *parent_device; NMSettingVlan *s_vlan; /* Change MAC address to parent's one if needed */ @@ -553,9 +549,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_vlan = { static void nm_device_vlan_class_init(NMDeviceVlanClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; @@ -599,11 +595,11 @@ nm_device_vlan_class_init(NMDeviceVlanClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VLAN_DEVICE_FACTORY, NMVlanDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_VLAN, NM_DEVICE_IFACE, @@ -622,9 +618,9 @@ create_device(NMDeviceFactory * factory, static const char * get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) { - NMSettingVlan * s_vlan; + NMSettingVlan *s_vlan; NMSettingWired *s_wired; - const char * parent = NULL; + const char *parent = NULL; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_VLAN_SETTING_NAME), NULL); @@ -646,7 +642,7 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) static char * get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { - const char * ifname; + const char *ifname; NMSettingVlan *s_vlan; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_VLAN_SETTING_NAME), NULL); diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index c752fa0a..ae80e1d4 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -44,7 +44,7 @@ static void do_update_properties(NMDeviceVrf *self, const NMPlatformLnkVrf *props) { NMDeviceVrfPrivate *priv = NM_DEVICE_VRF_GET_PRIVATE(self); - GObject * object = G_OBJECT(self); + GObject *object = G_OBJECT(self); NMPlatformLnkVrf props_null; if (!props) { @@ -72,7 +72,7 @@ do_update_properties(NMDeviceVrf *self, const NMPlatformLnkVrf *props) static void update_properties(NMDevice *device) { - NMDeviceVrf * self = NM_DEVICE_VRF(device); + NMDeviceVrf *self = NM_DEVICE_VRF(device); const NMPlatformLnkVrf *props; props = nm_platform_link_get_lnk_vrf(nm_device_get_platform(device), @@ -110,15 +110,15 @@ unrealize_notify(NMDevice *device) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); + const char *iface = nm_device_get_iface(device); NMPlatformLnkVrf props = {}; - NMSettingVrf * s_vrf; + NMSettingVrf *s_vrf; int r; s_vrf = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VRF); @@ -145,7 +145,7 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMDeviceVrfPrivate *priv = NM_DEVICE_VRF_GET_PRIVATE(device); - NMSettingVrf * s_vrf; + NMSettingVrf *s_vrf; if (!NM_DEVICE_CLASS(nm_device_vrf_parent_class) ->check_connection_compatible(device, connection, error)) @@ -166,11 +166,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingVrf *s_vrf; @@ -200,7 +200,7 @@ static void update_connection(NMDevice *device, NMConnection *connection) { NMDeviceVrfPrivate *priv = NM_DEVICE_VRF_GET_PRIVATE(device); - NMSettingVrf * s_vrf = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VRF); + NMSettingVrf *s_vrf = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VRF); if (priv->props.table != nm_setting_vrf_get_table(s_vrf)) g_object_set(G_OBJECT(s_vrf), NM_SETTING_VRF_TABLE, priv->props.table, NULL); @@ -211,7 +211,7 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool { NMDeviceVrf *self = NM_DEVICE_VRF(device); gboolean success = TRUE; - const char * slave_iface = nm_device_get_ip_iface(slave); + const char *slave_iface = nm_device_get_ip_iface(slave); nm_device_master_check_slave_physical_port(device, slave, LOGD_DEVICE); @@ -303,9 +303,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_vrf = { static void nm_device_vrf_class_init(NMDeviceVrfClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; @@ -344,11 +344,11 @@ nm_device_vrf_class_init(NMDeviceVrfClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VRF_DEVICE_FACTORY, NMVrfDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_VRF, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device-vxlan.c b/src/core/devices/nm-device-vxlan.c index fcd6950b..bf7c94c0 100644 --- a/src/core/devices/nm-device-vxlan.c +++ b/src/core/devices/nm-device-vxlan.c @@ -16,7 +16,6 @@ #include "nm-setting-wired.h" #include "settings/nm-settings.h" #include "nm-act-request.h" -#include "nm-ip4-config.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" @@ -65,9 +64,9 @@ G_DEFINE_TYPE(NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE) static void update_properties(NMDevice *device) { - NMDeviceVxlan * self = NM_DEVICE_VXLAN(device); - NMDeviceVxlanPrivate * priv = NM_DEVICE_VXLAN_GET_PRIVATE(self); - GObject * object = G_OBJECT(device); + NMDeviceVxlan *self = NM_DEVICE_VXLAN(device); + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE(self); + GObject *object = G_OBJECT(device); const NMPlatformLnkVxlan *props; props = nm_platform_link_get_lnk_vxlan(nm_device_get_platform(device), @@ -140,7 +139,7 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) static void unrealize_notify(NMDevice *device) { - NMDeviceVxlan * self = NM_DEVICE_VXLAN(device); + NMDeviceVxlan *self = NM_DEVICE_VXLAN(device); NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE(self); guint i; @@ -153,16 +152,16 @@ unrealize_notify(NMDevice *device) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { - const char * iface = nm_device_get_iface(device); + const char *iface = nm_device_get_iface(device); NMPlatformLnkVxlan props = {}; - NMSettingVxlan * s_vxlan; - const char * str; + NMSettingVxlan *s_vxlan; + const char *str; int r; s_vxlan = nm_connection_get_setting_vxlan(connection); @@ -242,8 +241,8 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE(device); - NMSettingVxlan * s_vxlan; - const char * parent; + NMSettingVxlan *s_vxlan; + const char *parent; if (!NM_DEVICE_CLASS(nm_device_vxlan_parent_class) ->check_connection_compatible(device, connection, error)) @@ -367,11 +366,11 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingVxlan *s_vxlan; @@ -605,9 +604,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_vxlan = { static void nm_device_vxlan_class_init(NMDeviceVxlanClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; @@ -745,11 +744,11 @@ nm_device_vxlan_class_init(NMDeviceVxlanClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_VXLAN_DEVICE_FACTORY, NMVxlanDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_VXLAN, NM_DEVICE_IFACE, @@ -779,7 +778,7 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) static char * get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { - const char * ifname; + const char *ifname; NMSettingVxlan *s_vxlan; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_VXLAN_SETTING_NAME), NULL); diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index f129478f..bdb96cb2 100644 --- a/src/core/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -12,12 +12,13 @@ #include "nm-setting-wireguard.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "nm-l3-config-data.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-glib-aux/nm-secret-utils.h" #include "nm-device-private.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nmp-object.h" -#include "libnm-platform/nmp-rules-manager.h" +#include "libnm-platform/nmp-route-manager.h" #include "nm-device-factory.h" #include "nm-active-connection.h" #include "nm-act-request.h" @@ -178,9 +179,9 @@ static NM_UTILS_LOOKUP_STR_DEFINE(_link_config_mode_to_string, static void _auto_default_route_get_enabled(NMSettingWireGuard *s_wg, - NMConnection * connection, - gboolean * out_enabled_v4, - gboolean * out_enabled_v6) + NMConnection *connection, + gboolean *out_enabled_v4, + gboolean *out_enabled_v6) { NMTernary enabled_v4; NMTernary enabled_v6; @@ -326,7 +327,7 @@ static void _auto_default_route_init(NMDeviceWireGuard *self) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - NMConnection * connection; + NMConnection *connection; gboolean enabled_v4 = FALSE; gboolean enabled_v6 = FALSE; gboolean refreshing_only; @@ -379,12 +380,12 @@ _auto_default_route_init(NMDeviceWireGuard *self) static GPtrArray * get_extra_rules(NMDevice *device) { - NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device); - NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(device); + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); gs_unref_ptrarray GPtrArray *extra_rules = NULL; guint32 priority = 0; int is_ipv4; - NMConnection * connection; + NMConnection *connection; _auto_default_route_init(self); @@ -456,7 +457,7 @@ get_extra_rules(NMDevice *device) static guint32 coerce_route_table(NMDevice *device, int addr_family, guint32 route_table, gboolean is_user_config) { - NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device); + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(device); NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); gboolean auto_default_route_enabled; @@ -580,7 +581,7 @@ static PeerData * _peers_add(NMDeviceWireGuard *self, NMWireGuardPeer *peer) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - PeerData * peer_data; + PeerData *peer_data; nm_assert(peer); nm_assert(nm_wireguard_peer_is_sealed(peer)); @@ -605,9 +606,9 @@ _peers_add(NMDeviceWireGuard *self, NMWireGuardPeer *peer) static gboolean _peers_resolve_retry_timeout(gpointer user_data) { - NMDeviceWireGuard * self = user_data; + NMDeviceWireGuard *self = user_data; NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - PeerData * peer_data; + PeerData *peer_data; gint64 now; gint64 next; @@ -683,7 +684,7 @@ _peers_resolve_retry_reschedule(NMDeviceWireGuard *self, gint64 new_next_try_at_ static void _peers_resolve_retry_reschedule_for_peer(NMDeviceWireGuard *self, - PeerData * peer_data, + PeerData *peer_data, gint64 retry_in_msec) { nm_assert(retry_in_msec >= 0); @@ -725,16 +726,16 @@ _peers_retry_in_msec(PeerData *peer_data, gboolean after_failure) static void _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - NMDeviceWireGuard * self; + NMDeviceWireGuard *self; NMDeviceWireGuardPrivate *priv; - PeerData * peer_data; - gs_free_error GError *resolv_error = NULL; - GList * list; - gboolean changed; - NMSockAddrUnion sockaddr; - gint64 retry_in_msec; - char s_sockaddr[100]; - char s_retry[100]; + PeerData *peer_data; + gs_free_error GError *resolv_error = NULL; + GList *list; + gboolean changed; + NMSockAddrUnion sockaddr; + gint64 retry_in_msec; + char s_sockaddr[100]; + char s_retry[100]; list = g_resolver_lookup_by_name_finish(G_RESOLVER(source_object), res, &resolv_error); @@ -782,7 +783,7 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) GList *iter; for (iter = list; iter; iter = iter->next) { - GInetAddress * a = iter->data; + GInetAddress *a = iter->data; NMSockAddrUnion sockaddr_tmp; NMSockAddrUnion *s; @@ -874,9 +875,9 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) static void _peers_resolve_start(NMDeviceWireGuard *self, PeerData *peer_data) { - NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); gs_unref_object GResolver *resolver = NULL; - const char * host; + const char *host; resolver = g_resolver_get_default(); @@ -913,7 +914,7 @@ static void _peers_resolve_reresolve_all(NMDeviceWireGuard *self) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - PeerData * peer_data; + PeerData *peer_data; c_list_for_each_entry (peer_data, &priv->lst_peers_head, lst_peers) { if (peer_data->ep_resolv.cancellable) { @@ -931,13 +932,13 @@ _peers_resolve_reresolve_all(NMDeviceWireGuard *self) static gboolean _peers_update(NMDeviceWireGuard *self, - PeerData * peer_data, - NMWireGuardPeer * peer, + PeerData *peer_data, + NMWireGuardPeer *peer, gboolean force_update) { nm_auto_unref_wgpeer NMWireGuardPeer *old_peer = NULL; - NMSockAddrEndpoint * old_endpoint; - NMSockAddrEndpoint * endpoint; + NMSockAddrEndpoint *old_endpoint; + NMSockAddrEndpoint *endpoint; gboolean endpoint_changed = FALSE; gboolean changed; NMSockAddrUnion sockaddr; @@ -1018,7 +1019,7 @@ static void _peers_remove_all(NMDeviceWireGuard *self) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - PeerData * peer_data; + PeerData *peer_data; while ((peer_data = c_list_first_entry(&priv->lst_peers_head, PeerData, lst_peers))) _peers_remove(self, peer_data); @@ -1028,8 +1029,8 @@ static void _peers_update_all(NMDeviceWireGuard *self, NMSettingWireGuard *s_wg, gboolean *out_peers_removed) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - PeerData * peer_data_safe; - PeerData * peer_data; + PeerData *peer_data_safe; + PeerData *peer_data; guint i, n; gboolean peers_removed = FALSE; @@ -1061,22 +1062,22 @@ _peers_update_all(NMDeviceWireGuard *self, NMSettingWireGuard *s_wg, gboolean *o } static void -_peers_get_platform_list(NMDeviceWireGuardPrivate * priv, +_peers_get_platform_list(NMDeviceWireGuardPrivate *priv, LinkConfigMode config_mode, - NMPWireGuardPeer ** out_peers, + NMPWireGuardPeer **out_peers, NMPlatformWireGuardChangePeerFlags **out_peer_flags, - guint * out_len, - GArray ** out_allowed_ips_data) + guint *out_len, + GArray **out_allowed_ips_data) { - gs_free NMPWireGuardPeer *plpeers = NULL; + gs_free NMPWireGuardPeer *plpeers = NULL; gs_free NMPlatformWireGuardChangePeerFlags *plpeer_flags = NULL; - gs_unref_array GArray *allowed_ips = NULL; - PeerData * peer_data; - guint i_good; - guint n_aip; - guint i_aip; - guint len; - guint i; + gs_unref_array GArray *allowed_ips = NULL; + PeerData *peer_data; + guint i_good; + guint n_aip; + guint i_aip; + guint len; + guint i; nm_assert(out_peers && !*out_peers); nm_assert(out_peer_flags && !*out_peer_flags); @@ -1096,7 +1097,7 @@ _peers_get_platform_list(NMDeviceWireGuardPrivate * priv, i_good = 0; c_list_for_each_entry (peer_data, &priv->lst_peers_head, lst_peers) { NMPlatformWireGuardChangePeerFlags *plf = &plpeer_flags[i_good]; - NMPWireGuardPeer * plp = &plpeers[i_good]; + NMPWireGuardPeer *plp = &plpeers[i_good]; NMSettingSecretFlags psk_secret_flags; if (!nm_utils_base64secret_decode(nm_wireguard_peer_get_public_key(peer_data->peer), @@ -1211,9 +1212,9 @@ skip: static void update_properties(NMDevice *device) { - NMDeviceWireGuard * self; - NMDeviceWireGuardPrivate * priv; - const NMPlatformLink * plink; + NMDeviceWireGuard *self; + NMDeviceWireGuardPrivate *priv; + const NMPlatformLink *plink; const NMPlatformLnkWireGuard *props = NULL; int ifindex; @@ -1273,11 +1274,11 @@ get_generic_capabilities(NMDevice *dev) /*****************************************************************************/ static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { const char *iface = nm_device_get_iface(device); int r; @@ -1312,14 +1313,14 @@ _secrets_cancel(NMDeviceWireGuard *self) } static void -_secrets_cb(NMActRequest * req, +_secrets_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * connection, - GError * error, + NMSettingsConnection *connection, + GError *error, gpointer user_data) { - NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(user_data); - NMDevice * device = NM_DEVICE(self); + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(user_data); + NMDevice *device = NM_DEVICE(self); NMDeviceWireGuardPrivate *priv; g_return_if_fail(NM_IS_DEVICE_WIREGUARD(self)); @@ -1348,13 +1349,13 @@ _secrets_cb(NMActRequest * req, } static void -_secrets_get_secrets(NMDeviceWireGuard * self, - const char * setting_name, +_secrets_get_secrets(NMDeviceWireGuard *self, + const char *setting_name, NMSecretAgentGetSecretsFlags flags, - const char *const * hints) + const char *const *hints) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - NMActRequest * req; + NMActRequest *req; _secrets_cancel(self); @@ -1369,8 +1370,8 @@ _secrets_get_secrets(NMDeviceWireGuard * self, static NMActStageReturn _secrets_handle_auth_or_fail(NMDeviceWireGuard *self, NMActRequest *req, gboolean new_secrets) { - NMConnection * applied_connection; - const char * setting_name; + NMConnection *applied_connection; + const char *setting_name; gs_unref_ptrarray GPtrArray *hints = NULL; if (!nm_device_auth_retries_try_next(NM_DEVICE(self))) @@ -1415,22 +1416,22 @@ _dns_config_changed(NMDnsManager *dns_manager, NMDeviceWireGuard *self) /*****************************************************************************/ static NMActStageReturn -link_config(NMDeviceWireGuard * self, - const char * reason, +link_config(NMDeviceWireGuard *self, + const char *reason, LinkConfigMode config_mode, NMDeviceStateReason *out_failure_reason) { - NMDeviceWireGuardPrivate * priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - nm_auto_bzero_secret_ptr NMSecretPtr wg_lnk_clear_private_key = NM_SECRET_PTR_INIT(); - NMSettingWireGuard * s_wg; - NMConnection * connection; - NMActStageReturn ret; - gs_unref_array GArray *allowed_ips_data = NULL; - NMPlatformLnkWireGuard wg_lnk; - gs_free NMPWireGuardPeer *plpeers = NULL; + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + nm_auto_bzero_secret_ptr NMSecretPtr wg_lnk_clear_private_key = NM_SECRET_PTR_INIT(); + NMSettingWireGuard *s_wg; + NMConnection *connection; + NMActStageReturn ret; + gs_unref_array GArray *allowed_ips_data = NULL; + NMPlatformLnkWireGuard wg_lnk; + gs_free NMPWireGuardPeer *plpeers = NULL; gs_free NMPlatformWireGuardChangePeerFlags *plpeer_flags = NULL; guint plpeers_len = 0; - const char * setting_name; + const char *setting_name; gboolean peers_removed; NMPlatformWireGuardChangeFlags wg_change_flags; int ifindex; @@ -1583,7 +1584,7 @@ link_config_delayed_resolver_cb(gpointer user_data) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device); + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(device); NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); NMDeviceSysIfaceState sys_iface_state; NMDeviceStateReason failure_reason; @@ -1625,19 +1626,19 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) return ret; } -static NMIPConfig * +static const NML3ConfigData * _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family) { - NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - gs_unref_object NMIPConfig *ip_config = NULL; - NMConnection * connection; - NMSettingWireGuard * s_wg; - guint n_peers; - guint i; - int ip_ifindex; - guint32 route_metric; - guint32 route_table_coerced; - gboolean auto_default_route_enabled; + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + NMConnection *connection; + NMSettingWireGuard *s_wg; + guint n_peers; + guint i; + int ip_ifindex; + guint32 route_metric; + guint32 route_table_coerced; + gboolean auto_default_route_enabled; _auto_default_route_init(self); @@ -1693,7 +1694,7 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family) for (j = 0; j < n_aips; j++) { NMPlatformIPXRoute rt; NMIPAddr addrbin; - const char * aip; + const char *aip; gboolean valid; int prefix; guint32 rtable_coerced; @@ -1715,11 +1716,10 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family) continue; } - if (!ip_config) { - ip_config = nm_device_ip_config_new(NM_DEVICE(self), addr_family); - nm_ip_config_set_config_flags(ip_config, - NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES, - 0); + if (!l3cd) { + l3cd = nm_device_create_l3_config_data(NM_DEVICE(self), NM_IP_CONFIG_SOURCE_USER); + nm_l3_config_data_set_flags(l3cd, + NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES); } nm_utils_ipx_address_clear_host_address(addr_family, &addrbin, NULL, prefix); @@ -1754,27 +1754,23 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family) }; } - nm_ip_config_add_route(ip_config, &rt.rx, NULL); + nm_l3_config_data_add_route(l3cd, addr_family, NULL, &rt.rx); } } - return g_steal_pointer(&ip_config); + if (!l3cd) + return NULL; + + return nm_l3_config_data_seal(g_steal_pointer(&l3cd)); } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static void +act_stage3_ip_config(NMDevice *device, int addr_family) { - gs_unref_object NMIPConfig *ip_config = NULL; + nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; - ip_config = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family); - - nm_device_set_dev2_ip_config(device, addr_family, ip_config); - - return NM_DEVICE_CLASS(nm_device_wireguard_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + l3cd = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family); + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd); } static guint32 @@ -1819,7 +1815,7 @@ _device_cleanup(NMDeviceWireGuard *self) } static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) @@ -1833,12 +1829,12 @@ device_state_changed(NMDevice * device, /*****************************************************************************/ static gboolean -can_reapply_change(NMDevice * device, +can_reapply_change(NMDevice *device, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { if (nm_streq(setting_name, NM_SETTING_WIREGUARD_SETTING_NAME)) { /* Most, but not all WireGuard settings can be reapplied. Whitelist. @@ -1864,11 +1860,9 @@ can_reapply_change(NMDevice * device, static void reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new) { - NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device); - NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - gs_unref_object NMIPConfig *ip4_config = NULL; - gs_unref_object NMIPConfig *ip6_config = NULL; - NMDeviceState state = nm_device_get_state(device); + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(device); + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + NMDeviceState state = nm_device_get_state(device); NM_DEVICE_CLASS(nm_device_wireguard_parent_class)->reapply_connection(device, con_old, con_new); @@ -1878,11 +1872,14 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne } if (state >= NM_DEVICE_STATE_IP_CONFIG) { - ip4_config = _get_dev2_ip_config(self, AF_INET); - ip6_config = _get_dev2_ip_config(self, AF_INET6); + nm_auto_unref_l3cd const NML3ConfigData *l3cd_4 = NULL; + nm_auto_unref_l3cd const NML3ConfigData *l3cd_6 = NULL; + + l3cd_4 = _get_dev2_ip_config(self, AF_INET); + l3cd_6 = _get_dev2_ip_config(self, AF_INET6); - nm_device_set_dev2_ip_config(device, AF_INET, ip4_config); - nm_device_set_dev2_ip_config(device, AF_INET6, ip6_config); + nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, l3cd_4); + nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_READY, l3cd_6); } } @@ -1893,7 +1890,7 @@ update_connection(NMDevice *device, NMConnection *connection) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(device); NMSettingWireGuard *s_wg = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIREGUARD); - const NMPObject * obj_wg; + const NMPObject *obj_wg; const NMPObjectLnkWireGuard *olnk_wg; guint i; @@ -1914,7 +1911,7 @@ update_connection(NMDevice *device, NMConnection *connection) for (i = 0; i < olnk_wg->peers_len; i++) { nm_auto_unref_wgpeer NMWireGuardPeer *peer = NULL; - const NMPWireGuardPeer * ppeer = &olnk_wg->peers[i]; + const NMPWireGuardPeer *ppeer = &olnk_wg->peers[i]; peer = nm_wireguard_peer_new(); @@ -1929,7 +1926,7 @@ update_connection(NMDevice *device, NMConnection *connection) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(object); + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(object); NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); switch (prop_id) { @@ -1974,7 +1971,7 @@ dispose(GObject *object) static void finalize(GObject *object) { - NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(object); + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(object); NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); nm_explicit_bzero(priv->lnk_curr.private_key, sizeof(priv->lnk_curr.private_key)); @@ -2007,9 +2004,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_wireguard = { static void nm_device_wireguard_class_init(NMDeviceWireGuardClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; object_class->dispose = dispose; @@ -2025,7 +2022,7 @@ nm_device_wireguard_class_init(NMDeviceWireGuardClass *klass) device_class->create_and_realize = create_and_realize; device_class->act_stage2_config = act_stage2_config; device_class->act_stage2_config_also_for_external_or_assume = TRUE; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage3_ip_config = act_stage3_ip_config; device_class->get_generic_capabilities = get_generic_capabilities; device_class->link_changed = link_changed; device_class->update_connection = update_connection; @@ -2069,11 +2066,11 @@ nm_device_wireguard_class_init(NMDeviceWireGuardClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WIREGUARD_DEVICE_FACTORY, NMWireGuardDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_WIREGUARD, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device-wpan.c b/src/core/devices/nm-device-wpan.c index 9bc43a85..f7b712ea 100644 --- a/src/core/devices/nm-device-wpan.c +++ b/src/core/devices/nm-device-wpan.c @@ -14,7 +14,6 @@ #include "nm-act-request.h" #include "nm-device-private.h" -#include "nm-ip4-config.h" #include "libnm-platform/nm-platform.h" #include "nm-device-factory.h" #include "nm-setting-wpan.h" @@ -39,11 +38,11 @@ G_DEFINE_TYPE(NMDeviceWpan, nm_device_wpan, NM_TYPE_DEVICE) /*****************************************************************************/ static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingWpan *s_wpan; @@ -79,7 +78,7 @@ static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { NMSettingWpan *s_wpan; - const char * mac, *hw_addr; + const char *mac, *hw_addr; if (!NM_DEVICE_CLASS(nm_device_wpan_parent_class) ->check_connection_compatible(device, connection, error)) @@ -104,17 +103,17 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceWpan * self = NM_DEVICE_WPAN(device); - NMSettingWpan * s_wpan; - NMPlatform * platform; + NMDeviceWpan *self = NM_DEVICE_WPAN(device); + NMSettingWpan *s_wpan; + NMPlatform *platform; guint16 pan_id; guint16 short_address; gint16 page, channel; int ifindex; - const guint8 * hwaddr; + const guint8 *hwaddr; gsize hwaddr_len = 0; const NMPlatformLink *lowpan_plink; - NMDevice * lowpan_device = NULL; + NMDevice *lowpan_device = NULL; NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; platform = nm_device_get_platform(device); @@ -203,7 +202,7 @@ static const NMDBusInterfaceInfoExtended interface_info_device_wpan = { static void nm_device_wpan_class_init(NMDeviceWpanClass *klass) { - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_wpan); @@ -225,11 +224,11 @@ nm_device_wpan_class_init(NMDeviceWpanClass *klass) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_WPAN_DEVICE_FACTORY, NMWpanDeviceFactory)) static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return g_object_new(NM_TYPE_DEVICE_WPAN, NM_DEVICE_IFACE, diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index ea1b9647..696c0df8 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -34,22 +34,23 @@ #include "nm-device-private.h" #include "nm-l3cfg.h" #include "nm-l3-config-data.h" +#include "nm-l3-ipv4ll.h" +#include "nm-l3-ipv6ll.h" #include "NetworkManagerUtils.h" #include "nm-manager.h" #include "libnm-platform/nm-platform.h" #include "libnm-platform/nm-platform-utils.h" #include "libnm-platform/nmp-object.h" -#include "libnm-platform/nmp-rules-manager.h" +#include "libnm-platform/nmp-route-manager.h" #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" + #include "dhcp/nm-dhcp-manager.h" #include "dhcp/nm-dhcp-utils.h" #include "nm-act-request.h" -#include "nm-proxy-config.h" -#include "nm-ip4-config.h" -#include "nm-ip6-config.h" #include "nm-pacrunner-manager.h" #include "dnsmasq/nm-dnsmasq-manager.h" +#include "nm-ip-config.h" #include "nm-dhcp-config.h" #include "nm-rfkill-manager.h" #include "nm-firewall-utils.h" @@ -66,7 +67,6 @@ #include "nm-config.h" #include "c-list/src/c-list.h" #include "dns/nm-dns-manager.h" -#include "nm-acd-manager.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-systemd-core/nm-sd.h" #include "nm-lldp-listener.h" @@ -86,19 +86,7 @@ #define DEFAULT_AUTOCONNECT TRUE -static guint32 -dhcp_grace_period_from_timeout(guint32 timeout) -{ -#define DHCP_GRACE_PERIOD_MULTIPLIER 2U - - nm_assert(timeout > 0); - nm_assert(timeout < G_MAXINT32); - - if (timeout < G_MAXUINT32 / DHCP_GRACE_PERIOD_MULTIPLIER) - return timeout * DHCP_GRACE_PERIOD_MULTIPLIER; - - return G_MAXUINT32; -} +#define GRACE_PERIOD_MULTIPLIER 2U #define CARRIER_WAIT_TIME_MS 6000 #define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000 @@ -117,6 +105,13 @@ typedef enum { CLEANUP_TYPE_DECONFIGURE, } CleanupType; +typedef enum _nm_packed { + ADDR_METHOD_STATE_DISABLED, + ADDR_METHOD_STATE_PENDING, + ADDR_METHOD_STATE_GOOD, + ADDR_METHOD_STATE_FAILED, +} AddrMethodState; + typedef struct { CList lst_slave; NMDevice *slave; @@ -131,36 +126,72 @@ typedef struct { } DeleteOnDeactivateData; typedef struct { - NMDevice * device; - GCancellable * cancellable; + NMDevice *device; + GCancellable *cancellable; NMPlatformAsyncCallback callback; gpointer callback_data; guint num_vfs; NMOptionBool autoprobe; } SriovOp; -typedef void (*AcdCallback)(NMDevice *, NMIP4Config **, gboolean); - typedef enum { /* The various NML3ConfigData types that we track explicitly. Note that * their relative order matters: higher numbers in this enum means more - * important (and during merge overwrites other settings). */ + * important (and during merge overwrites other settings). This is passed + * as priority to nm_l3cfg_add_config(). */ + L3_CONFIG_DATA_TYPE_LL_4, + L3_CONFIG_DATA_TYPE_LL_6, + +#define L3_CONFIG_DATA_TYPE_LL_X(IS_IPv4) \ + ((IS_IPv4) ? L3_CONFIG_DATA_TYPE_LL_4 : L3_CONFIG_DATA_TYPE_LL_6) + L3_CONFIG_DATA_TYPE_AC_6, + L3_CONFIG_DATA_TYPE_PD_6, + L3_CONFIG_DATA_TYPE_DHCP_4, L3_CONFIG_DATA_TYPE_DHCP_6, - L3_CONFIG_DATA_TYPE_DEV_4, - L3_CONFIG_DATA_TYPE_DEV_6, - L3_CONFIG_DATA_TYPE_SETTING, + +#define L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4) \ + ((IS_IPv4) ? L3_CONFIG_DATA_TYPE_DHCP_4 : L3_CONFIG_DATA_TYPE_DHCP_6) + + L3_CONFIG_DATA_TYPE_SHARED_4, + L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC, + L3_CONFIG_DATA_TYPE_DEVIP_4, + L3_CONFIG_DATA_TYPE_DEVIP_6, + +#define L3_CONFIG_DATA_TYPE_DEVIP(addr_family) \ + ({ \ + L3ConfigDataType _t; \ + \ + switch (addr_family) { \ + case AF_INET: \ + _t = L3_CONFIG_DATA_TYPE_DEVIP_4; \ + break; \ + case AF_INET6: \ + _t = L3_CONFIG_DATA_TYPE_DEVIP_6; \ + break; \ + default: \ + nm_assert_not_reached(); \ + /* fall-through */ \ + case AF_UNSPEC: \ + _t = L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC; \ + break; \ + } \ + \ + _t; \ + }) + + L3_CONFIG_DATA_TYPE_MANUALIP, + _L3_CONFIG_DATA_TYPE_NUM, _L3_CONFIG_DATA_TYPE_NONE, + _L3_CONFIG_DATA_TYPE_ACD_ONLY, } L3ConfigDataType; -typedef struct { - AcdCallback callback; - NMDevice * device; - NMIP4Config **configs; -} AcdData; +G_STATIC_ASSERT(NM_L3CFG_CONFIG_PRIORITY_IPV4LL == L3_CONFIG_DATA_TYPE_LL_4); +G_STATIC_ASSERT(NM_L3CFG_CONFIG_PRIORITY_IPV6LL == L3_CONFIG_DATA_TYPE_LL_6); +G_STATIC_ASSERT(NM_L3CFG_CONFIG_PRIORITY_VPN == L3_CONFIG_DATA_TYPE_DEVIP_6); typedef enum { HW_ADDR_TYPE_UNSET = 0, @@ -177,26 +208,81 @@ typedef enum { } FirewallState; typedef struct { - NMIPConfig *orig; /* the original configuration applied to the device */ - NMIPConfig *current; /* configuration after external changes. NULL means - * that the original configuration didn't change. */ -} AppliedConfig; + NMIPConfig *ip_config; +} L3IPData; typedef struct { - NMDhcpClient *client; - NMDhcpConfig *config; - gulong notify_sigid; - guint grace_id; - bool grace_pending : 1; - bool was_active : 1; -} DhcpData; + GSource *check_async_source; + GSource *req_timeout_source; + union { + const NMDeviceIPState state; + NMDeviceIPState state_; + }; + bool wait_for_carrier : 1; + bool wait_for_ports : 1; + bool is_disabled : 1; + bool is_ignore : 1; + bool do_reapply : 1; +} IPStateData; + +typedef struct { + NMDhcpClient *client; + NMDhcpConfig *config; + gulong notify_sigid; + NMDeviceIPState state; + union { + struct { + } v4; + struct { + guint needed_prefixes; + NMNDiscDHCPLevel mode; + } v6; + }; +} IPDhcpStateData; + +typedef struct { + NMDeviceIPState state; + NMDeviceStateReason failed_reason; +} IPDevStateData; + +typedef struct { + NMDeviceIPState state; + union { + struct { + NMDnsMasqManager *dnsmasq_manager; + NMNetnsSharedIPHandle *shared_ip_handle; + NMFirewallConfig *firewall_config; + gulong dnsmasq_state_id; + const NML3ConfigData *l3cd; + } v4; + struct { + } v6; + }; +} IPSharedStateData; + +typedef struct { + NMDeviceIPState state; + union { + struct { + NML3IPv4LL *ipv4ll; + NML3IPv4LLRegistration *ipv4ll_registation; + GSource *timeout_source; + } v4; + struct { + NML3IPv6LL *ipv6ll; + GSource *retry_source; + NML3IPv6LLState llstate; + struct in6_addr lladdr; + } v6; + }; +} IPLLStateData; struct _NMDeviceConnectivityHandle { CList concheck_lst; - NMDevice * self; + NMDevice *self; NMDeviceConnectivityCallback callback; gpointer user_data; - NMConnectivityCheckHandle * c_handle; + NMConnectivityCheckHandle *c_handle; guint64 seq; bool is_periodic : 1; bool is_periodic_bump : 1; @@ -209,8 +295,8 @@ typedef struct { NMEthtoolFeatureStates *features; NMOptionBool requested[_NM_ETHTOOL_ID_FEATURE_NUM]; NMEthtoolCoalesceState *coalesce; - NMEthtoolRingState * ring; - NMEthtoolPauseState * pause; + NMEthtoolRingState *ring; + NMEthtoolPauseState *pause; } EthtoolState; typedef enum { @@ -223,8 +309,8 @@ typedef struct { ResolverState state; GInetAddress *address; GCancellable *cancellable; - char * hostname; - NMDevice * device; + char *hostname; + NMDevice *device; guint timeout_id; /* Used when waiting for the address */ int addr_family; } HostnameResolver; @@ -234,14 +320,14 @@ typedef struct { enum { STATE_CHANGED, AUTOCONNECT_ALLOWED, - IP4_CONFIG_CHANGED, - IP6_CONFIG_CHANGED, + L3CD_CHANGED, IP6_PREFIX_DELEGATED, IP6_SUBNET_NEEDED, REMOVED, RECHECK_AUTO_ACTIVATE, RECHECK_ASSUME, DNS_LOOKUP_DONE, + PLATFORM_ADDRESS_CHANGED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = {0}; @@ -260,6 +346,9 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice, PROP_IP4_ADDRESS, PROP_IP4_CONFIG, PROP_DHCP4_CONFIG, + +#define PROP_DHCPX_CONFIG(IS_IPv4) ((IS_IPv4) ? PROP_DHCP4_CONFIG : PROP_DHCP6_CONFIG) + PROP_IP6_CONFIG, PROP_DHCP6_CONFIG, PROP_STATE, @@ -294,8 +383,6 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice, PROP_PORTS, ); typedef struct _NMDevicePrivate { - bool in_state_changed; - guint device_link_changed_id; guint device_ip_link_changed_id; @@ -309,22 +396,12 @@ typedef struct _NMDevicePrivate { NMDeviceStateReason reason; } queued_state; - union { - struct { - guint queued_ip_config_id_6; - guint queued_ip_config_id_4; - }; - guint queued_ip_config_id_x[2]; - }; - struct { const char **arr; guint len; guint alloc; } pending_actions; - GSList *dad6_failed_addrs; - NMDBusTrackObjPath parent_device; char *udi; @@ -332,23 +409,41 @@ typedef struct _NMDevicePrivate { union { const char *const iface; - char * iface_; + char *iface_; }; union { const char *const ip_iface; - char * ip_iface_; + char *ip_iface_; }; union { + NML3Cfg *const l3cfg; + NML3Cfg *l3cfg_; + }; + + union { + struct { + L3IPData l3ipdata_6; + L3IPData l3ipdata_4; + }; + L3IPData l3ipdata_x[2]; + }; + + NML3CfgCommitTypeHandle *l3cfg_commit_type; + + union { const int ifindex; int ifindex_; }; + union { const int ip_ifindex; int ip_ifindex_; }; - NMNetnsSharedIPHandle *shared_ip_handle; + union { + const NML3ConfigData *d; + } l3cds[_L3_CONFIG_DATA_TYPE_NUM]; int parent_ifindex; @@ -371,22 +466,21 @@ typedef struct _NMDevicePrivate { bool real : 1; - bool update_ip_config_completed_v4 : 1; - bool update_ip_config_completed_v6 : 1; - NMDeviceType type; - char * type_desc; + char *type_desc; NMLinkType link_type; NMDeviceCapabilities capabilities; - char * driver; - char * driver_version; - char * firmware_version; + char *driver; + char *driver_version; + char *firmware_version; RfKillType rfkill_type; bool firmware_missing : 1; bool nm_plugin_missing : 1; bool hw_addr_perm_fake : 1; /* whether the permanent HW address could not be read and is a fake */ + guint8 in_state_changed : 4; + NMUtilsStableType current_stable_id_type : 3; bool nm_owned : 1; /* whether the device is a device owned and created by NM */ @@ -397,10 +491,10 @@ typedef struct _NMDevicePrivate { guint64 udi_id; GHashTable *available_connections; - char * hw_addr; - char * hw_addr_perm; - char * hw_addr_initial; - char * physical_port_id; + char *hw_addr; + char *hw_addr_perm; + char *hw_addr_initial; + char *physical_port_id; guint dev_id; NMUnmanagedFlags unmanaged_mask; @@ -410,25 +504,12 @@ typedef struct _NMDevicePrivate { GCancellable *deactivating_cancellable; - NMActRequest * queued_act_request; + NMActRequest *queued_act_request; bool queued_act_request_is_waiting_for_carrier : 1; NMDBusTrackObjPath act_request; - union { - struct { - guint activation_source_id_6; - guint activation_source_id_4; /* for layer2 and IPv4. */ - }; - guint activation_source_id_x[2]; - }; - - union { - struct { - ActivationHandleFunc activation_source_func_6; - ActivationHandleFunc activation_source_func_4; /* for layer2 and IPv4. */ - }; - ActivationHandleFunc activation_source_func_x[2]; - }; + GSource *activation_idle_source; + ActivationHandleFunc activation_func; guint recheck_assume_id; @@ -452,7 +533,7 @@ typedef struct _NMDevicePrivate { gulong config_changed_id; gulong ifindex_changed_id; guint32 mtu; - guint32 ip6_mtu; + guint32 ip6_mtu; /* FIXME(l3cfg) */ guint32 mtu_initial; guint32 ip6_mtu_initial; NMDeviceMtuSource mtu_source; @@ -469,6 +550,14 @@ typedef struct _NMDevicePrivate { gint64 carrier_wait_until_ms; union { + struct { + NML3ConfigMergeFlags l3config_merge_flags_6; + NML3ConfigMergeFlags l3config_merge_flags_4; + }; + NML3ConfigMergeFlags l3config_merge_flags_x[2]; + }; + + union { const NMDeviceSysIfaceState sys_iface_state; NMDeviceSysIfaceState sys_iface_state_; }; @@ -478,12 +567,6 @@ typedef struct _NMDevicePrivate { bool up : 1; /* IFF_UP */ - bool v4_commit_first_time : 1; - bool v6_commit_first_time : 1; - - bool default_route_metric_penalty_ip4_has : 1; - bool default_route_metric_penalty_ip6_has : 1; - bool v4_route_table_initialized : 1; bool v6_route_table_initialized : 1; @@ -496,165 +579,115 @@ typedef struct _NMDevicePrivate { bool is_enslaved : 1; - bool ipv6ll_handle : 1; /* TRUE if NM handles the device's IPv6LL address */ - bool ipv6ll_has : 1; - bool ndisc_started : 1; bool device_link_changed_down : 1; bool concheck_rp_filter_checked : 1; - NMDeviceStageState stage1_sriov_state : 3; - - bool ip_config_started : 1; bool tc_committed : 1; - char *current_stable_id; + NMDeviceStageState stage1_sriov_state : 3; - union { - struct { - GSource *ip_req_timeout_source_6; - GSource *ip_req_timeout_source_4; - }; - GSource *ip_req_timeout_source_x[2]; - }; + char *current_stable_id; - /* Proxy Configuration */ - NMProxyConfig * proxy_config; NMPacrunnerConfId *pacrunner_conf_id; - /* IP configuration info. Combined config from VPN, settings, and device */ + struct { + union { + const NMDeviceIPState state; + NMDeviceIPState state_; + }; + } ip_data; + union { struct { - NMIP6Config *ip_config_6; - NMIP4Config *ip_config_4; + IPStateData ip_data_6; + IPStateData ip_data_4; }; - NMIPConfig *ip_config_x[2]; + IPStateData ip_data_x[2]; }; - /* Config from DHCP, PPP, LLv4, etc */ - AppliedConfig dev_ip_config_4; + struct { + GSource *carrier_timeout; + union { + struct { + NMDeviceIPState state_6; + NMDeviceIPState state_4; + }; + NMDeviceIPState state_x[2]; + }; + bool carrier_timeout_expired; + } ipmanual_data; - /* config from the setting */ union { struct { - NMIP6Config *con_ip_config_6; - NMIP4Config *con_ip_config_4; + IPDhcpStateData ipdhcp_data_6; + IPDhcpStateData ipdhcp_data_4; }; - NMIPConfig *con_ip_config_x[2]; + IPDhcpStateData ipdhcp_data_x[2]; }; - /* Stuff added outside NM */ + struct { + NMNDisc *ndisc; + GSource *ndisc_grace_source; + gulong ndisc_changed_id; + gulong ndisc_timeout_id; + NMDeviceIPState state; + const NML3ConfigData *l3cd; + } ipac6_data; + union { struct { - NMIP6Config *ext_ip_config_6; - NMIP4Config *ext_ip_config_4; + IPLLStateData ipll_data_6; + IPLLStateData ipll_data_4; }; - NMIPConfig *ext_ip_config_x[2]; + IPLLStateData ipll_data_x[2]; }; - /* VPNs which use this device */ union { struct { - GSList *vpn_configs_6; - GSList *vpn_configs_4; + IPSharedStateData ipshared_data_6; + IPSharedStateData ipshared_data_4; }; - GSList *vpn_configs_x[2]; + IPSharedStateData ipshared_data_x[2]; }; - /* Extra device configuration, injected by the subclass of NMDevice. - * This is used for example by NMDeviceModem for WWAN configuration. */ union { struct { - AppliedConfig dev2_ip_config_6; - AppliedConfig dev2_ip_config_4; + IPDevStateData ipdev_data_6; + IPDevStateData ipdev_data_4; }; - AppliedConfig dev2_ip_config_x[2]; + IPDevStateData ipdev_data_x[2]; }; - /* DHCPv4 tracking */ - struct { - char *pac_url; - } dhcp4; + IPDevStateData ipdev_data_unspec; struct { - /* IP6 config from DHCP */ - AppliedConfig ip6_config; - /* Event ID of the current IP6 config from DHCP */ - char * event_id; - NMNDiscDHCPLevel mode; - guint needed_prefixes; - } dhcp6; + /* If we set the addrgenmode6, this records the previously set value. */ + guint8 previous_mode_val; - union { - struct { - DhcpData dhcp_data_6; - DhcpData dhcp_data_4; - }; - DhcpData dhcp_data_x[2]; - }; + /* whether @previous_mode_val is set. */ + bool previous_mode_has : 1; + } addrgenmode6_data; struct { NMLogDomain log_domain; guint timeout; guint watch; GPid pid; - char * binary; - char * address; + char *binary; + char *address; guint deadline; } gw_ping; - /* dnsmasq stuff for shared connections */ - NMDnsMasqManager *dnsmasq_manager; - gulong dnsmasq_state_id; - /* Firewall */ FirewallState fw_state : 4; - NMFirewalldManager * fw_mgr; + NMFirewalldManager *fw_mgr; NMFirewalldManagerCallId *fw_call; - /* IPv4LL stuff */ - sd_ipv4ll *ipv4ll; - guint ipv4ll_timeout; - guint rt6_temporary_not_available_id; - - /* IPv4 DAD stuff */ - struct { - GSList * dad_list; - NMAcdManager *announcing; - } acd; - - union { - struct { - const NMDeviceIPState ip_state_6; - const NMDeviceIPState ip_state_4; - }; - union { - const NMDeviceIPState ip_state_x[2]; - NMDeviceIPState ip_state_x_[2]; - }; - }; - - AppliedConfig ac_ip6_config; /* config from IPv6 autoconfiguration */ - NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */ - NMIP6Config * dad6_ip6_config; - struct in6_addr ipv6ll_addr; - - GHashTable *rt6_temporary_not_available; - - NMNDisc * ndisc; - gulong ndisc_changed_id; - gulong ndisc_timeout_id; - NMSettingIP6ConfigPrivacy ndisc_use_tempaddr; - - guint linklocal6_timeout_id; - guint8 linklocal6_dad_counter; - GHashTable *ip6_saved_properties; EthtoolState *ethtool_state; - gboolean needs_ip6_subnet; - /* master interface for bridge/bond/team slave */ NMDevice *master; gulong master_ready_id; @@ -666,7 +699,7 @@ typedef struct _NMDevicePrivate { NMMetered metered; NMSettings *settings; - NMManager * manager; + NMManager *manager; NMNetns *netns; @@ -710,9 +743,12 @@ typedef struct _NMDevicePrivate { bool mtu_force_set_done : 1; + bool needs_ip6_subnet : 1; + NMOptionBool promisc_reset; GVariant *ports_variant; /* Array of port devices D-Bus path */ + char *prop_ip_iface; /* IP interface D-Bus property */ } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -724,58 +760,83 @@ G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) static const NMDBusInterfaceInfoExtended interface_info_device; static const GDBusSignalInfo signal_info_state_changed; -static void nm_device_set_proxy_config(NMDevice *self, const char *pac_url); - -static gboolean update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs); +static void _dev_l3_cfg_commit(NMDevice *self, gboolean do_sync); -static gboolean nm_device_set_ip_config(NMDevice * self, - int addr_family, - NMIPConfig *config, - gboolean commit, - GPtrArray * ip4_dev_route_blacklist); - -static gboolean ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit); +static void _dev_l3_cfg_commit_type_reset(NMDevice *self); static gboolean nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure); static void nm_device_slave_notify_enslave(NMDevice *self, gboolean success); static void nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason); -static void addrconf6_start_with_link_ready(NMDevice *self); -static gboolean linklocal6_start(NMDevice *self); +static void _dev_ipll6_start(NMDevice *self); -static guint32 default_route_metric_penalty_get(NMDevice *self, int addr_family); +static void _dev_ipac6_start_continue(NMDevice *self); +static void _dev_ipac6_ndisc_set_router_config(NMDevice *self); -static guint _prop_get_ipv4_dad_timeout(NMDevice *self); +static guint32 _dev_default_route_metric_penalty_get(NMDevice *self, int addr_family); -static NMIP6Config *dad6_get_pending_addresses(NMDevice *self); +static guint32 _prop_get_ipv4_dad_timeout(NMDevice *self); static void _carrier_wait_check_queued_act_request(NMDevice *self); static gint64 _get_carrier_wait_ms(NMDevice *self); +static GBytes *_prop_get_ipv6_dhcp_duid(NMDevice *self, + NMConnection *connection, + GBytes *hwaddr, + gboolean *out_enforce); + static const char *_activation_func_to_string(ActivationHandleFunc func); static void _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gboolean quitting); -static void queued_state_clear(NMDevice *device); -static gboolean queued_ip4_config_change(gpointer user_data); -static gboolean queued_ip6_config_change(gpointer user_data); -static void ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data); -static gboolean ip_config_valid(NMDeviceState state); -static NMActStageReturn dhcp4_start(NMDevice *self); -static gboolean dhcp6_start(NMDevice *self, gboolean wait_for_ll); -static void nm_device_start_ip_check(NMDevice *self); -static void realize_start_setup(NMDevice * self, - const NMPlatformLink *plink, - gboolean assume_state_guess_assume, - const char * assume_state_connection_uuid, - gboolean set_nm_owned, - NMUnmanFlagOp unmanaged_user_explicit, - gboolean force_platform_init); -static void _set_mtu(NMDevice *self, guint32 mtu); -static void _commit_mtu(NMDevice *self, const NMIP4Config *config); -static void _cancel_activation(NMDevice *self); - -static void concheck_update_state(NMDevice * self, +static void queued_state_clear(NMDevice *device); +static void ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data); +static void nm_device_start_ip_check(NMDevice *self); +static void realize_start_setup(NMDevice *self, + const NMPlatformLink *plink, + gboolean assume_state_guess_assume, + const char *assume_state_connection_uuid, + gboolean set_nm_owned, + NMUnmanFlagOp unmanaged_user_explicit, + gboolean force_platform_init); +static void _set_mtu(NMDevice *self, guint32 mtu); +static void _commit_mtu(NMDevice *self); +static void _cancel_activation(NMDevice *self); + +static void _dev_ipll4_notify_event(NMDevice *self); + +static void _dev_ip_state_check(NMDevice *self, int addr_family); + +static void _dev_ipmanual_check_ready(NMDevice *self); + +static void +_dev_ipdhcpx_cleanup(NMDevice *self, int addr_family, gboolean reset_dhcp_config, gboolean release); + +static void _dev_ip_state_check_async(NMDevice *self, int addr_family); + +static void _dev_ipdhcpx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state); + +static void _dev_ipdhcpx_restart(NMDevice *self, int addr_family, gboolean release); + +static gboolean +_dev_ipac6_grace_period_start(NMDevice *self, guint32 timeout_sec, gboolean force_restart); + +static void _dev_ipac6_start(NMDevice *self); + +static void _dev_ipac6_set_state(NMDevice *self, NMDeviceIPState state); + +static void +_dev_unmanaged_check_external_down(NMDevice *self, gboolean only_if_unmanaged, gboolean now); + +static void _dev_ipshared4_start(NMDevice *self); +static void _dev_ipshared4_spawn_dnsmasq(NMDevice *self); + +static void _dev_ipshared6_start(NMDevice *self); + +static void +_cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gboolean from_reapply); + +static void concheck_update_state(NMDevice *self, int addr_family, NMConnectivityState state, gboolean is_periodic); @@ -783,8 +844,80 @@ static void concheck_update_state(NMDevice * self, static void sriov_op_cb(GError *error, gpointer user_data); static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self); -static gboolean device_link_changed(NMDevice *self); -static void check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update); +static gboolean device_link_changed(gpointer user_data); +static gboolean _get_maybe_ipv6_disabled(NMDevice *self); + +/*****************************************************************************/ + +#define _NMLOG_addr_family(level, prefix, addr_family, fmt, ...) \ + G_STMT_START \ + { \ + const int _addr_family2 = (addr_family); \ + \ + _NMLOG(level, \ + (_addr_family2 == AF_UNSPEC ? LOGD_IP : LOGD_IPX(NM_IS_IPv4(_addr_family2))), \ + "" prefix "%s: " fmt, \ + nm_utils_addr_family_to_str(_addr_family2), \ + ##__VA_ARGS__); \ + } \ + G_STMT_END + +#define _NMLOG_ip(level, ...) _NMLOG_addr_family(level, "ip", __VA_ARGS__) +#define _LOGT_ip(...) _NMLOG_ip(LOGL_TRACE, __VA_ARGS__) +#define _LOGD_ip(...) _NMLOG_ip(LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_ip(...) _NMLOG_ip(LOGL_INFO, __VA_ARGS__) +#define _LOGW_ip(...) _NMLOG_ip(LOGL_WARN, __VA_ARGS__) + +#define _NMLOG_ipll(level, ...) _NMLOG_addr_family(level, "ip:ll", __VA_ARGS__) +#define _LOGT_ipll(...) _NMLOG_ipll(LOGL_TRACE, __VA_ARGS__) +#define _LOGD_ipll(...) _NMLOG_ipll(LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_ipll(...) _NMLOG_ipll(LOGL_INFO, __VA_ARGS__) +#define _LOGW_ipll(...) _NMLOG_ipll(LOGL_WARN, __VA_ARGS__) + +#define _NMLOG_ipdev(level, ...) _NMLOG_addr_family(level, "ip:dev", __VA_ARGS__) +#define _LOGT_ipdev(...) _NMLOG_ipdev(LOGL_TRACE, __VA_ARGS__) +#define _LOGD_ipdev(...) _NMLOG_ipdev(LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_ipdev(...) _NMLOG_ipdev(LOGL_INFO, __VA_ARGS__) +#define _LOGW_ipdev(...) _NMLOG_ipdev(LOGL_WARN, __VA_ARGS__) + +#define _NMLOG_ipdhcp(level, ...) _NMLOG_addr_family(level, "ip:dhcp", __VA_ARGS__) +#define _LOGT_ipdhcp(...) _NMLOG_ipdhcp(LOGL_TRACE, __VA_ARGS__) +#define _LOGD_ipdhcp(...) _NMLOG_ipdhcp(LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_ipdhcp(...) _NMLOG_ipdhcp(LOGL_INFO, __VA_ARGS__) +#define _LOGW_ipdhcp(...) _NMLOG_ipdhcp(LOGL_WARN, __VA_ARGS__) + +#define _NMLOG_ipshared(level, ...) _NMLOG_addr_family(level, "ip:shared", __VA_ARGS__) +#define _LOGT_ipshared(...) _NMLOG_ipshared(LOGL_TRACE, __VA_ARGS__) +#define _LOGD_ipshared(...) _NMLOG_ipshared(LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_ipshared(...) _NMLOG_ipshared(LOGL_INFO, __VA_ARGS__) +#define _LOGW_ipshared(...) _NMLOG_ipshared(LOGL_WARN, __VA_ARGS__) + +#define _NMLOG_ipac6(level, ...) _NMLOG_addr_family(level, "ip:ac6", AF_UNSPEC, __VA_ARGS__) +#define _LOGT_ipac6(...) _NMLOG_ipac6(LOGL_TRACE, __VA_ARGS__) +#define _LOGD_ipac6(...) _NMLOG_ipac6(LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_ipac6(...) _NMLOG_ipac6(LOGL_INFO, __VA_ARGS__) +#define _LOGW_ipac6(...) _NMLOG_ipac6(LOGL_WARN, __VA_ARGS__) + +#define _NMLOG_ipmanual(level, ...) _NMLOG_addr_family(level, "ip:manual", __VA_ARGS__) +#define _LOGT_ipmanual(...) _NMLOG_ipmanual(LOGL_TRACE, __VA_ARGS__) +#define _LOGD_ipmanual(...) _NMLOG_ipmanual(LOGL_DEBUG, __VA_ARGS__) +#define _LOGI_ipmanual(...) _NMLOG_ipmanual(LOGL_INFO, __VA_ARGS__) +#define _LOGW_ipmanual(...) _NMLOG_ipmanual(LOGL_WARN, __VA_ARGS__) + +/*****************************************************************************/ + +#define _CACHED_BOOL(cached_value, cmd) \ + ({ \ + NMTernary *const _cached_value = (cached_value); \ + \ + nm_assert(_cached_value); \ + nm_assert_is_ternary(*_cached_value); \ + \ + if (*_cached_value == NM_TERNARY_DEFAULT) \ + *_cached_value = !!(cmd); \ + \ + !!(*_cached_value); \ + }) /*****************************************************************************/ @@ -803,6 +936,38 @@ _hostname_resolver_free(HostnameResolver *resolver) /*****************************************************************************/ +/** + * Update the "ip_iface" property when something changes (device + * state, ifindex) and emit a notify signal if needed. Note that + * the property must be NULL for devices without an ifindex and + * when the device is not activated. This behavior is part of the + * API and should not be changed. + */ +static void +update_prop_ip_iface(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const char *ip_iface = NULL; + gs_free char *to_free = NULL; + + if (nm_device_get_ip_ifindex(self) > 0 + && (priv->state == NM_DEVICE_STATE_UNMANAGED + || (priv->state >= NM_DEVICE_STATE_IP_CHECK + && priv->state <= NM_DEVICE_STATE_DEACTIVATING))) { + ip_iface = nm_utils_str_utf8safe_escape(nm_device_get_ip_iface(self), + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, + &to_free); + } + + if (!nm_streq0(priv->prop_ip_iface, ip_iface)) { + g_free(priv->prop_ip_iface); + priv->prop_ip_iface = to_free ? g_steal_pointer(&to_free) : g_strdup(ip_iface); + _notify(self, PROP_IP_IFACE); + } +} + +/*****************************************************************************/ + static NMSettingIP6ConfigPrivacy _ip6_privacy_clamp(NMSettingIP6ConfigPrivacy use_tempaddr) { @@ -819,8 +984,8 @@ _ip6_privacy_clamp(NMSettingIP6ConfigPrivacy use_tempaddr) /*****************************************************************************/ static const char * -_prop_get_connection_stable_id(NMDevice * self, - NMConnection * connection, +_prop_get_connection_stable_id(NMDevice *self, + NMConnection *connection, NMUtilsStableType *out_stable_type) { NMDevicePrivate *priv; @@ -839,13 +1004,13 @@ _prop_get_connection_stable_id(NMDevice * self, * Especially with ${RANDOM} stable-id we want to generate *one* configuration * for each activation. */ if (G_UNLIKELY(!priv->current_stable_id)) { - gs_free char * generated = NULL; + gs_free char *generated = NULL; NMUtilsStableType stable_type; NMSettingConnection *s_con; gboolean hwaddr_is_fake; - const char * hwaddr; - const char * stable_id; - const char * uuid; + const char *hwaddr; + const char *stable_id; + const char *uuid; s_con = nm_connection_get_setting_connection(connection); @@ -907,18 +1072,18 @@ _prop_get_connection_stable_id(NMDevice * self, } static GBytes * -_prop_get_ipv6_dhcp_duid(NMDevice * self, +_prop_get_ipv6_dhcp_duid(NMDevice *self, NMConnection *connection, - GBytes * hwaddr, - gboolean * out_enforce) + GBytes *hwaddr, + gboolean *out_enforce) { NMSettingIPConfig *s_ip6; - const char * duid; - const char * duid_error; - GBytes * duid_out; + const char *duid; + const char *duid_error; + GBytes *duid_out; gboolean duid_enforce = TRUE; - gs_free char * logstr1 = NULL; - const guint8 * hwaddr_bin; + gs_free char *logstr1 = NULL; + const guint8 *hwaddr_bin; gsize hwaddr_len; int arp_type; @@ -979,12 +1144,12 @@ _prop_get_ipv6_dhcp_duid(NMDevice * self, * * Implementations that are added later, should use a distinct salt instead, * like "stable-ll"/"stable-llt" with ARPHRD_INFINIBAND below. */ - const guint32 DEFAULT_SALT = 670531087u; - nm_auto_free_checksum GChecksum *sum = NULL; + const guint32 DEFAULT_SALT = 670531087u; + nm_auto_free_checksum GChecksum *sum = NULL; NMUtilsStableType stable_type; - const char * stable_id = NULL; + const char *stable_id = NULL; guint32 salted_header; - const guint8 * host_id; + const guint8 *host_id; gsize host_id_len; union { guint8 sha256[NM_UTILS_CHECKSUM_LENGTH_SHA256]; @@ -1157,7 +1322,7 @@ _prop_get_ipv6_ra_timeout(NMDevice *self) static NMSettingConnectionMdns _prop_get_connection_mdns(NMDevice *self) { - NMConnection * connection; + NMConnection *connection; NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_CONNECTION_MDNS_DEFAULT); @@ -1179,7 +1344,7 @@ _prop_get_connection_mdns(NMDevice *self) static NMSettingConnectionLlmnr _prop_get_connection_llmnr(NMDevice *self) { - NMConnection * connection; + NMConnection *connection; NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_CONNECTION_LLMNR_DEFAULT); @@ -1201,7 +1366,7 @@ _prop_get_connection_llmnr(NMDevice *self) static NMSettingConnectionDnsOverTls _prop_get_connection_dns_over_tls(NMDevice *self) { - NMConnection * connection; + NMConnection *connection; NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); @@ -1224,14 +1389,14 @@ _prop_get_connection_dns_over_tls(NMDevice *self) static guint32 _prop_get_ipvx_route_table(NMDevice *self, int addr_family) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMDeviceClass * klass; - NMConnection * connection; - NMSettingIPConfig * s_ip; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDeviceClass *klass; + NMConnection *connection; + NMSettingIPConfig *s_ip; guint32 route_table = 0; gboolean is_user_config = TRUE; NMSettingConnection *s_con; - NMSettingVrf * s_vrf; + NMSettingVrf *s_vrf; nm_assert_addr_family(addr_family); @@ -1311,8 +1476,8 @@ _prop_get_ipvx_route_table(NMDevice *self, int addr_family) static gboolean _prop_get_connection_lldp(NMDevice *self) { - NMConnection * connection; - NMSettingConnection * s_con; + NMConnection *connection; + NMSettingConnection *s_con; NMSettingConnectionLldp lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT; connection = nm_device_get_applied_connection(self); @@ -1335,10 +1500,10 @@ _prop_get_connection_lldp(NMDevice *self) return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX; } -static guint +static guint32 _prop_get_ipv4_dad_timeout(NMDevice *self) { - NMConnection * connection; + NMConnection *connection; NMSettingIPConfig *s_ip4 = NULL; int timeout = -1; @@ -1347,6 +1512,9 @@ _prop_get_ipv4_dad_timeout(NMDevice *self) s_ip4 = nm_connection_get_setting_ip4_config(connection); if (s_ip4) timeout = nm_setting_ip_config_get_dad_timeout(s_ip4); + + nm_assert(timeout >= -1 && timeout <= NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX); + if (timeout >= 0) return timeout; @@ -1362,9 +1530,9 @@ static guint32 _prop_get_ipvx_dhcp_timeout(NMDevice *self, int addr_family) { NMDeviceClass *klass; - NMConnection * connection; - int timeout_i; + NMConnection *connection; guint32 timeout; + int timeout_i; nm_assert(NM_IS_DEVICE(self)); nm_assert_addr_family(addr_family); @@ -1407,9 +1575,40 @@ out: } static guint32 +_prop_get_ipvx_dns_priority(NMDevice *self, int addr_family) +{ + NMConnection *connection; + NMSettingIPConfig *s_ip; + int prio = 0; + + connection = nm_device_get_applied_connection(self); + s_ip = nm_connection_get_setting_ip_config(connection, addr_family); + if (s_ip) + prio = nm_setting_ip_config_get_dns_priority(s_ip); + + if (prio == 0) { + prio = nm_config_data_get_connection_default_int64( + NM_CONFIG_GET_DATA, + NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.dns-priority") + : NM_CON_DEFAULT("ipv6.dns-priority"), + self, + G_MININT32, + G_MAXINT32, + 0); + if (prio == 0) { + prio = nm_device_is_vpn(self) ? NM_DNS_PRIORITY_DEFAULT_VPN + : NM_DNS_PRIORITY_DEFAULT_NORMAL; + } + } + + nm_assert(prio != 0); + return prio; +} + +static guint32 _prop_get_ipvx_required_timeout(NMDevice *self, int addr_family) { - NMConnection * connection; + NMConnection *connection; NMSettingIPConfig *s_ip; int timeout; @@ -1440,6 +1639,25 @@ _prop_get_ipvx_required_timeout(NMDevice *self, int addr_family) 0); } +static gboolean +_prop_get_ipvx_may_fail(NMDevice *self, int addr_family) +{ + NMConnection *connection; + NMSettingIPConfig *s_ip = NULL; + + connection = nm_device_get_applied_connection(self); + if (connection) + s_ip = nm_connection_get_setting_ip_config(connection, addr_family); + + return !s_ip || nm_setting_ip_config_get_may_fail(s_ip); +} + +static gboolean +_prop_get_ipvx_may_fail_cached(NMDevice *self, int addr_family, NMTernary *cache) +{ + return _CACHED_BOOL(cache, _prop_get_ipvx_may_fail(self, addr_family)); +} + /** * _prop_get_ipvx_dhcp_iaid: * @self: the #NMDevice @@ -1453,18 +1671,18 @@ _prop_get_ipvx_required_timeout(NMDevice *self, int addr_family) * Returns: a IAID value for this device and the given connection. */ static guint32 -_prop_get_ipvx_dhcp_iaid(NMDevice * self, +_prop_get_ipvx_dhcp_iaid(NMDevice *self, int addr_family, NMConnection *connection, gboolean log_silent, - gboolean * out_is_explicit) + gboolean *out_is_explicit) { const int IS_IPv4 = NM_IS_IPv4(addr_family); NMSettingIPConfig *s_ip; - const char * iaid_str; + const char *iaid_str; guint32 iaid; - const char * iface; - const char * fail_reason; + const char *iface; + const char *fail_reason; gboolean is_explicit = TRUE; s_ip = nm_connection_get_setting_ip_config(connection, addr_family); @@ -1528,9 +1746,9 @@ _prop_get_ipvx_dhcp_iaid(NMDevice * self, nm_auto_free_checksum GChecksum *sum = NULL; guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1]; NMUtilsStableType stable_type; - const char * stable_id; + const char *stable_id; guint32 salted_header; - const guint8 * host_id; + const guint8 *host_id; gsize host_id_len; stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); @@ -1583,9 +1801,9 @@ out_good: static NMDhcpHostnameFlags _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family) { - NMConnection * connection; - NMSettingIPConfig * s_ip; - NMDhcpHostnameFlags flags; + NMConnection *connection; + NMSettingIPConfig *s_ip; + NMDhcpHostnameFlags flags; gs_free_error GError *error = NULL; g_return_val_if_fail(NM_IS_DEVICE(self), NM_DHCP_HOSTNAME_FLAG_NONE); @@ -1660,15 +1878,15 @@ static GBytes * _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes *hwaddr) { NMSettingIPConfig *s_ip4; - const char * client_id; - guint8 * client_id_buf; - const char * fail_reason; + const char *client_id; + guint8 *client_id_buf; + const char *fail_reason; guint8 hwaddr_bin_buf[_NM_UTILS_HWADDR_LEN_MAX]; - const guint8 * hwaddr_bin; + const guint8 *hwaddr_bin; int arp_type; gsize hwaddr_len; - GBytes * result; - gs_free char * logstr1 = NULL; + GBytes *result; + gs_free char *logstr1 = NULL; s_ip4 = nm_connection_get_setting_ip4_config(connection); client_id = nm_setting_ip4_config_get_dhcp_client_id(NM_SETTING_IP4_CONFIG(s_ip4)); @@ -1739,7 +1957,7 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes * gs_unref_bytes GBytes *duid = NULL; gboolean iaid_is_explicit; guint32 iaid; - const guint8 * duid_arr; + const guint8 *duid_arr; gsize duid_len; iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET, connection, FALSE, &iaid_is_explicit); @@ -1764,9 +1982,9 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes * nm_auto_free_checksum GChecksum *sum = NULL; guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1]; NMUtilsStableType stable_type; - const char * stable_id; + const char *stable_id; guint32 salted_header; - const guint8 * host_id; + const guint8 *host_id; gsize host_id_len; stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); @@ -1812,9 +2030,9 @@ static GBytes * _prop_get_ipv4_dhcp_vendor_class_identifier(NMDevice *self, NMSettingIP4Config *s_ip4) { gs_free char *to_free = NULL; - const char * conn_prop; - GBytes * bytes = NULL; - const char * bin; + const char *conn_prop; + GBytes *bytes = NULL; + const char *bin; gsize len; conn_prop = nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4); @@ -1848,7 +2066,7 @@ static NMSettingIP6ConfigPrivacy _prop_get_ipv6_ip6_privacy(NMDevice *self) { NMSettingIP6ConfigPrivacy ip6_privacy; - NMConnection * connection; + NMConnection *connection; g_return_val_if_fail(self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); @@ -1895,7 +2113,7 @@ _prop_get_ipv6_ip6_privacy(NMDevice *self) static const char * _prop_get_x_cloned_mac_address(NMDevice *self, NMConnection *connection, gboolean is_wifi) { - NMSetting * setting; + NMSetting *setting; const char *addr = NULL; setting = nm_connection_get_setting(connection, @@ -1941,7 +2159,7 @@ _prop_get_x_cloned_mac_address(NMDevice *self, NMConnection *connection, gboolea static const char * _prop_get_x_generate_mac_address_mask(NMDevice *self, NMConnection *connection, gboolean is_wifi) { - NMSetting * setting; + NMSetting *setting; const char *value; setting = nm_connection_get_setting(connection, @@ -1967,7 +2185,7 @@ _prop_get_x_generate_mac_address_mask(NMDevice *self, NMConnection *connection, static void _ethtool_features_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state) { - gs_free NMEthtoolFeatureStates *features; + gs_free NMEthtoolFeatureStates *features = NULL; features = g_steal_pointer(ðtool_state->features); @@ -1982,9 +2200,9 @@ _ethtool_features_reset(NMDevice *self, NMPlatform *platform, EthtoolState *etht } static void -_ethtool_features_set(NMDevice * self, - NMPlatform * platform, - EthtoolState * ethtool_state, +_ethtool_features_set(NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state, NMSettingEthtool *s_ethtool) { gs_free NMEthtoolFeatureStates *features = NULL; @@ -2033,18 +2251,18 @@ _ethtool_coalesce_reset(NMDevice *self, NMPlatform *platform, EthtoolState *etht } static void -_ethtool_coalesce_set(NMDevice * self, - NMPlatform * platform, - EthtoolState * ethtool_state, +_ethtool_coalesce_set(NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state, NMSettingEthtool *s_ethtool) { NMEthtoolCoalesceState coalesce_old; NMEthtoolCoalesceState coalesce_new; gboolean has_old = FALSE; - GHashTable * hash; + GHashTable *hash; GHashTableIter iter; - const char * name; - GVariant * variant; + const char *name; + GVariant *variant; nm_assert(NM_IS_DEVICE(self)); nm_assert(NM_IS_PLATFORM(platform)); @@ -2111,17 +2329,17 @@ _ethtool_ring_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_ } static void -_ethtool_ring_set(NMDevice * self, - NMPlatform * platform, - EthtoolState * ethtool_state, +_ethtool_ring_set(NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state, NMSettingEthtool *s_ethtool) { NMEthtoolRingState ring_old; NMEthtoolRingState ring_new; - GHashTable * hash; + GHashTable *hash; GHashTableIter iter; - const char * name; - GVariant * variant; + const char *name; + GVariant *variant; gboolean has_old = FALSE; nm_assert(NM_IS_DEVICE(self)); @@ -2207,17 +2425,17 @@ _ethtool_pause_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool } static void -_ethtool_pause_set(NMDevice * self, - NMPlatform * platform, - EthtoolState * ethtool_state, +_ethtool_pause_set(NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state, NMSettingEthtool *s_ethtool) { NMEthtoolPauseState pause_old; NMEthtoolPauseState pause_new; - GHashTable * hash; + GHashTable *hash; GHashTableIter iter; - const char * name; - GVariant * variant; + const char *name; + GVariant *variant; gboolean has_old = FALSE; NMTernary pause_autoneg = NM_TERNARY_DEFAULT; NMTernary pause_rx = NM_TERNARY_DEFAULT; @@ -2297,8 +2515,8 @@ _ethtool_pause_set(NMDevice * self, static void _ethtool_state_reset(NMDevice *self) { - NMPlatform * platform = nm_device_get_platform(self); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMPlatform *platform = nm_device_get_platform(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gs_free EthtoolState *ethtool_state = g_steal_pointer(&priv->ethtool_state); if (!ethtool_state) @@ -2317,12 +2535,12 @@ _ethtool_state_reset(NMDevice *self) static void _ethtool_state_set(NMDevice *self) { - int ifindex; - NMPlatform * platform; - NMConnection * connection; - NMSettingEthtool *s_ethtool; + int ifindex; + NMPlatform *platform; + NMConnection *connection; + NMSettingEthtool *s_ethtool; gs_free EthtoolState *ethtool_state = NULL; - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); ifindex = nm_device_get_ip_ifindex(self); if (ifindex <= 0) @@ -2416,27 +2634,6 @@ concheck_get_mgr(NMDevice *self) return priv->concheck_mgr; } -NMIP4Config * -nm_device_ip4_config_new(NMDevice *self) -{ - return nm_ip4_config_new(nm_device_get_multi_index(self), nm_device_get_ip_ifindex(self)); -} - -NMIP6Config * -nm_device_ip6_config_new(NMDevice *self) -{ - return nm_ip6_config_new(nm_device_get_multi_index(self), nm_device_get_ip_ifindex(self)); -} - -NMIPConfig * -nm_device_ip_config_new(NMDevice *self, int addr_family) -{ - nm_assert_addr_family(addr_family); - - return NM_IS_IPv4(addr_family) ? (gpointer) nm_device_ip4_config_new(self) - : (gpointer) nm_device_ip6_config_new(self); -} - NML3ConfigData * nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source) { @@ -2451,98 +2648,29 @@ nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source) return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex, source); } -static void -applied_config_clear(AppliedConfig *config) -{ - g_clear_object(&config->current); - g_clear_object(&config->orig); -} - -static void -applied_config_init(AppliedConfig *config, gpointer ip_config) +const NML3ConfigData * +nm_device_create_l3_config_data_from_connection(NMDevice *self, NMConnection *connection) { - nm_assert(!ip_config || (!config->orig && !config->current) - || nm_ip_config_get_addr_family(ip_config) - == nm_ip_config_get_addr_family(config->orig ?: config->current)); - nm_assert(!ip_config || NM_IS_IP_CONFIG(ip_config)); - - nm_g_object_ref(ip_config); - applied_config_clear(config); - config->orig = ip_config; -} - -static void -applied_config_init_new(AppliedConfig *config, NMDevice *self, int addr_family) -{ - gs_unref_object NMIPConfig *c = nm_device_ip_config_new(self, addr_family); - - applied_config_init(config, c); -} - -static NMIPConfig * -applied_config_get_current(AppliedConfig *config) -{ - return config->current ?: config->orig; -} + NML3ConfigData *l3cd; + int ifindex; -static void -applied_config_add_address(AppliedConfig *config, const NMPlatformIPAddress *address) -{ - if (config->orig) - nm_ip_config_add_address(config->orig, address); - else - nm_assert(!config->current); - - if (config->current) - nm_ip_config_add_address(config->current, address); -} - -static void -applied_config_add_nameserver(AppliedConfig *config, const NMIPAddr *ns) -{ - if (config->orig) - nm_ip_config_add_nameserver(config->orig, ns); - else - nm_assert(!config->current); - - if (config->current) - nm_ip_config_add_nameserver(config->current, ns); -} - -static void -applied_config_add_search(AppliedConfig *config, const char *new) -{ - if (config->orig) - nm_ip_config_add_search(config->orig, new); - else - nm_assert(!config->current); - - if (config->current) - nm_ip_config_add_search(config->current, new); -} - -static void -applied_config_reset_searches(AppliedConfig *config) -{ - if (config->orig) - nm_ip_config_reset_searches(config->orig); - else - nm_assert(!config->current); + nm_assert(NM_IS_DEVICE(self)); + nm_assert(!connection || NM_IS_CONNECTION(connection)); - if (config->current) - nm_ip_config_reset_searches(config->current); -} + if (!connection) + return NULL; -static void -applied_config_reset_nameservers(AppliedConfig *config) -{ - if (config->orig) - nm_ip_config_reset_nameservers(config->orig); - else - nm_assert(!config->current); + ifindex = nm_device_get_ip_ifindex(self); + if (ifindex <= 0) + g_return_val_if_reached(NULL); - if (config->current) - nm_ip_config_reset_nameservers(config->current); + l3cd = + nm_l3_config_data_new_from_connection(nm_device_get_multi_index(self), ifindex, connection); + nm_l3_config_data_set_mdns(l3cd, _prop_get_connection_mdns(self)); + nm_l3_config_data_set_llmnr(l3cd, _prop_get_connection_llmnr(self)); + nm_l3_config_data_set_dns_over_tls(l3cd, _prop_get_connection_dns_over_tls(self)); + nm_l3_config_data_set_ip6_privacy(l3cd, _prop_get_ipv6_ip6_privacy(self)); + return l3cd; } /*****************************************************************************/ @@ -2588,6 +2716,7 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st nm_device_sys_iface_state_to_string(priv->sys_iface_state), nm_device_sys_iface_state_to_string(sys_iface_state)); priv->sys_iface_state_ = sys_iface_state; + _dev_l3_cfg_commit_type_reset(self); } /* this function only sets a flag, no immediate actions are initiated. @@ -2598,7 +2727,7 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st } static void -_active_connection_set_state_flags_full(NMDevice * self, +_active_connection_set_state_flags_full(NMDevice *self, NMActivationStateFlags flags, NMActivationStateFlags mask) { @@ -2618,12 +2747,12 @@ _active_connection_set_state_flags(NMDevice *self, NMActivationStateFlags flags) /*****************************************************************************/ static gboolean -set_interface_flags_full(NMDevice * self, +set_interface_flags_full(NMDevice *self, NMDeviceInterfaceFlags mask, NMDeviceInterfaceFlags interface_flags, gboolean notify) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceInterfaceFlags f; nm_assert(!!mask); @@ -2642,7 +2771,7 @@ set_interface_flags_full(NMDevice * self, } static gboolean -set_interface_flags(NMDevice * self, +set_interface_flags(NMDevice *self, NMDeviceInterfaceFlags interface_flags, gboolean set, gboolean notify) @@ -2654,8 +2783,8 @@ set_interface_flags(NMDevice * self, } void -nm_device_assume_state_get(NMDevice * self, - gboolean * out_assume_state_guess_assume, +nm_device_assume_state_get(NMDevice *self, + gboolean *out_assume_state_guess_assume, const char **out_assume_state_connection_uuid) { NMDevicePrivate *priv; @@ -2668,7 +2797,7 @@ nm_device_assume_state_get(NMDevice * self, } static void -_assume_state_set(NMDevice * self, +_assume_state_set(NMDevice *self, gboolean assume_state_guess_assume, const char *assume_state_connection_uuid) { @@ -2700,33 +2829,6 @@ nm_device_assume_state_reset(NMDevice *self) /*****************************************************************************/ -static void -init_ip_config_dns_priority(NMDevice *self, NMIPConfig *config) -{ - const char *property; - int priority; - - property = (nm_ip_config_get_addr_family(config) == AF_INET) - ? NM_CON_DEFAULT("ipv4.dns-priority") - : NM_CON_DEFAULT("ipv6.dns-priority"); - - priority = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, - property, - self, - G_MININT, - G_MAXINT, - 0); - - if (priority == 0) { - priority = - nm_device_is_vpn(self) ? NM_DNS_PRIORITY_DEFAULT_VPN : NM_DNS_PRIORITY_DEFAULT_NORMAL; - } - - nm_ip_config_set_dns_priority(config, priority); -} - -/*****************************************************************************/ - static char * nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property) { @@ -2744,7 +2846,7 @@ nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *proper } static gint64 -nm_device_sysctl_ip_conf_get_int_checked(NMDevice * self, +nm_device_sysctl_ip_conf_get_int_checked(NMDevice *self, int addr_family, const char *property, guint base, @@ -2771,59 +2873,15 @@ nm_device_sysctl_ip_conf_get_int_checked(NMDevice * self, fallback); } -static void -set_ipv6_token(NMDevice *self, const NMUtilsIPv6IfaceId *iid, const char *token_str) -{ - NMPlatform * platform; - int ifindex; - const NMPlatformLink *link; - char buf[32]; - gint64 val; - - /* Setting the kernel token is not strictly necessary as the - * IPv6 address is generated in userspace. However it is - * convenient so that users can see the token with iproute - * ('ip token'). */ - platform = nm_device_get_platform(self); - ifindex = nm_device_get_ip_ifindex(self); - link = nm_platform_link_get(platform, ifindex); - - if (link && link->inet6_token.id == iid->id) { - _LOGT(LOGD_DEVICE | LOGD_IP6, "token %s already set", token_str); - return; - } - - /* The kernel allows setting a token only when 'accept_ra' - * is 1: temporarily flip it if necessary; unfortunately - * this will also generate an additional Router Solicitation - * from kernel. */ - val = nm_device_sysctl_ip_conf_get_int_checked(self, - AF_INET6, - "accept_ra", - 10, - G_MININT32, - G_MAXINT32, - 1); - if (val != 1) - nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "1"); - - nm_platform_link_set_ipv6_token(platform, ifindex, iid); - - if (val != 1) { - nm_sprintf_buf(buf, "%d", (int) val); - nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", buf); - } -} - gboolean -nm_device_sysctl_ip_conf_set(NMDevice * self, +nm_device_sysctl_ip_conf_set(NMDevice *self, int addr_family, const char *property, const char *value) { - NMPlatform * platform = nm_device_get_platform(self); + NMPlatform *platform = nm_device_get_platform(self); gs_free char *value_to_free = NULL; - const char * ifname; + const char *ifname; nm_assert_addr_family(addr_family); @@ -2863,95 +2921,1064 @@ _add_capabilities(NMDevice *self, NMDeviceCapabilities capabilities) /*****************************************************************************/ +static void +_dev_ip_state_req_timeout_cancel(NMDevice *self, int addr_family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + if (addr_family == AF_UNSPEC) { + _dev_ip_state_req_timeout_cancel(self, AF_INET); + _dev_ip_state_req_timeout_cancel(self, AF_INET6); + return; + } + + if (nm_clear_g_source_inst(&priv->ip_data_x[NM_IS_IPv4(addr_family)].req_timeout_source)) + _LOGD_ip(addr_family, "required-timeout: cancelled"); +} + static gboolean -ip_required_timeout_x(NMDevice *self, int addr_family) +_dev_ip_state_req_timeout_cb_x(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - _LOGD(LOGD_CORE, - "required-timeout expired for IPv%c", - nm_utils_addr_family_to_char(addr_family)); - nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[NM_IS_IPv4(addr_family)]); - check_ip_state(self, FALSE, TRUE); + _LOGD_ip(addr_family, "required-timeout: expired"); + nm_clear_g_source_inst(&priv->ip_data_x[NM_IS_IPv4(addr_family)].req_timeout_source); + _dev_ip_state_check(self, nm_utils_addr_family_other(addr_family)); return G_SOURCE_CONTINUE; } static gboolean -ip_required_timeout_4(gpointer data) +_dev_ip_state_req_timeout_cb_4(gpointer user_data) { - return ip_required_timeout_x(data, AF_INET); + return _dev_ip_state_req_timeout_cb_x(user_data, AF_INET); } static gboolean -ip_required_timeout_6(gpointer data) +_dev_ip_state_req_timeout_cb_6(gpointer user_data) { - return ip_required_timeout_x(data, AF_INET6); + return _dev_ip_state_req_timeout_cb_x(user_data, AF_INET6); } static void -_set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state) +_dev_ip_state_req_timeout_schedule(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const int IS_IPv4 = NM_IS_IPv4(addr_family); - guint timeout_msec; - int v4; + guint32 timeout_msec; + char buf[32]; - nm_assert_addr_family(addr_family); + nm_assert(!priv->ip_data_x[IS_IPv4].req_timeout_source); - if (new_state == NM_DEVICE_IP_STATE_CONF && !priv->ip_config_started) { - /* Start the required-timeout timers when one of IPv4/IPv6 - * enters the CONF state. This means that if there is no carrier and - * ipv4.method=auto,ipv6.method=manual, the timeout for IPv4 will - * start as soon as connection is activated, even if DHCPv4 did not - * start yet. - */ - priv->ip_config_started = TRUE; + timeout_msec = _prop_get_ipvx_required_timeout(self, addr_family); + if (timeout_msec == 0) { + _LOGD_ip(addr_family, "required-timeout: disabled"); + return; + } - for (v4 = 1; v4 >= 0; v4--) { - char buf[32]; + _LOGD_ip(addr_family, + "required-timeout: started (%s msec)", + timeout_msec == G_MAXINT32 ? "∞" : nm_sprintf_buf(buf, "%u", timeout_msec)); - nm_assert(!priv->ip_req_timeout_source_x[v4]); - if ((timeout_msec = _prop_get_ipvx_required_timeout(self, v4 ? AF_INET : AF_INET6))) { - _LOGD(LOGD_CORE, - "required-timeout in %s msec for IPv%c", - timeout_msec == G_MAXINT32 ? "∞" : nm_sprintf_buf(buf, "%u", timeout_msec), - v4 ? '4' : '6'); + if (timeout_msec == G_MAXINT32) { + priv->ip_data_x[IS_IPv4].req_timeout_source = g_source_ref(nm_g_source_sentinel_get(0)); + } else { + priv->ip_data_x[IS_IPv4].req_timeout_source = nm_g_timeout_add_source( + timeout_msec, + IS_IPv4 ? _dev_ip_state_req_timeout_cb_4 : _dev_ip_state_req_timeout_cb_6, + self); + } +} - if (timeout_msec == G_MAXINT32) { - priv->ip_req_timeout_source_x[v4] = g_source_ref(nm_g_source_sentinel_get(0)); - } else { - priv->ip_req_timeout_source_x[v4] = - nm_g_timeout_add_source(timeout_msec, - v4 ? ip_required_timeout_4 : ip_required_timeout_6, - self); +static gboolean +_dev_ip_state_set_state(NMDevice *self, + int addr_family, + NMDeviceIPState ip_state, + const char *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int IS_IPv4; + + if (addr_family == AF_UNSPEC) { + if (priv->ip_data.state == ip_state) + return FALSE; + _LOGD_ip(addr_family, + "set (combined) state %s (was %s, reason: %s)", + nm_device_ip_state_to_string(ip_state), + nm_device_ip_state_to_string(priv->ip_data.state), + reason); + priv->ip_data.state_ = ip_state; + return TRUE; + } + + IS_IPv4 = NM_IS_IPv4(addr_family); + + if (priv->ip_data_x[IS_IPv4].state_ == ip_state) + return FALSE; + + _LOGD_ip(addr_family, + "set state %s (was %s, reason: %s)", + nm_device_ip_state_to_string(ip_state), + nm_device_ip_state_to_string(priv->ip_data_x[IS_IPv4].state), + reason); + priv->ip_data_x[IS_IPv4].state_ = ip_state; + return TRUE; +} + +static void +_device_ip_state_accumulate(NMDeviceIPState state, + gboolean *out_is_started, + gboolean *out_is_pending, + gboolean *out_is_failed) +{ + switch (state) { + case NM_DEVICE_IP_STATE_NONE: + return; + case NM_DEVICE_IP_STATE_PENDING: + *out_is_started = TRUE; + *out_is_pending = TRUE; + return; + case NM_DEVICE_IP_STATE_READY: + *out_is_started = TRUE; + return; + case NM_DEVICE_IP_STATE_FAILED: + *out_is_started = TRUE; + *out_is_failed = TRUE; + return; + } + nm_assert_not_reached(); + return; +} + +static void +_dev_ip_state_check(NMDevice *self, int addr_family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + gboolean s_is_started = FALSE; + gboolean s_is_failed = FALSE; + gboolean s_is_pending = FALSE; + gboolean v_bool; + NMDeviceIPState ip_state; + NMDeviceIPState ip_state_other; + NMDeviceIPState combinedip_state; + NMTernary may_fail = NM_TERNARY_DEFAULT; + NMTernary may_fail_other = NM_TERNARY_DEFAULT; + gboolean disabled_or_ignore = FALSE; + gboolean disabled_or_ignore_other = FALSE; + + if (priv->ip_data_x[IS_IPv4].is_disabled || priv->ip_data_x[IS_IPv4].is_ignore) + disabled_or_ignore = TRUE; + if (priv->ip_data_x[!IS_IPv4].is_disabled || priv->ip_data_x[!IS_IPv4].is_ignore) + disabled_or_ignore_other = TRUE; + + /* State handling in NMDevice: + * + * NMDevice manages a lot of state, that is for the various IP addressing methods, the state + * of the interface (controller/port), and a overall nm_device_get_state(). + * + * The idea is to compartmentalize these states into smaller units, and combine them as appropriate. + * + * For example, NMDhcpClient already provides an API that hides most of the complexity. But it still + * needs to expose some state, like whether we are still trying to get a lease (PENDING), whether there + * was a critical failure (FAILED) or we have a lease (READY). This state is grouped in NMDevice + * under priv->ipdhcp_data_x. Most important is priv->ipdhcp_data_x[].state, which distills all of this + * into 4 values of type NMDeviceIPState. This state is cached, so whenever something changes (e.g. + * an event from NMDhcpClient), we determine the new state and compare it with what is cached. If + * the cached state is as the new state, we are done. Otherwise, the change gets escalated (which + * means to call _dev_ip_state_check_async()). + * + * Then, the various sub-states escalate their changes to this function (_dev_ip_state_check). This + * function first takes the sub-states related to one IP address family, and combines them into + * priv->ip_data_x[] (and in particular priv->ip_data_x[].state). The same repeats. The current + * state is cached in priv->ip_data_x[].state, and _dev_ip_state_check() determines the new state. + * If there is no change, it ends here. Otherwise, it gets escalated. In this case, the escaplation + * happens in _dev_ip_state_check() below by combining the combined per-address-family into + * priv->ip_data. In particular this step needs to take into account settings like "may-fail" + * and "required-timeout". + * + * The escalation and compartmentalization priv->ip_data repeats. This time it escalates + * to the overall device state (nm_device_state_changed() and nm_device_get_state()), which then + * triggers larger state changes (e.g. the activation might fail). + */ + + if (priv->l3cfg && nm_l3cfg_commit_on_idle_is_scheduled(priv->l3cfg)) { + /* we have an update on NML3Cfg scheduled. We first process that, before + * progressing the IP state. When that's done, we will be called again. */ + _dev_ip_state_check_async(self, addr_family); + return; + } + + if (priv->ip_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_NONE) { + ip_state = NM_DEVICE_IP_STATE_NONE; + goto got_ip_state; + } + + if (nm_device_sys_iface_state_is_external(self)) { + ip_state = NM_DEVICE_IP_STATE_READY; + goto got_ip_state; + } + + if (priv->ip_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_PENDING + && (priv->state < NM_DEVICE_STATE_IP_CONFIG || priv->state > NM_DEVICE_STATE_ACTIVATED)) { + /* we can only leave pending state, if we are between (including) IP_CONFIG and ACTIVATED states. */ + ip_state = NM_DEVICE_IP_STATE_PENDING; + goto got_ip_state; + } + + if (priv->ip_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_PENDING + && nm_active_connection_get_master(NM_ACTIVE_CONNECTION(priv->act_request.obj)) + && !priv->is_enslaved) { + /* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the + * master to enslave us. */ + ip_state = NM_DEVICE_IP_STATE_PENDING; + goto got_ip_state; + } + + if (priv->ip_data_x[IS_IPv4].wait_for_carrier || priv->ip_data_x[IS_IPv4].wait_for_ports) { + ip_state = NM_DEVICE_IP_STATE_PENDING; + goto got_ip_state; + } + + if (disabled_or_ignore) { + ip_state = NM_DEVICE_IP_STATE_READY; + goto got_ip_state; + } + + _device_ip_state_accumulate(priv->ipmanual_data.state_x[IS_IPv4], + &s_is_started, + &s_is_pending, + &s_is_failed); + + _device_ip_state_accumulate(priv->ipll_data_x[IS_IPv4].state, + &s_is_started, + &s_is_pending, + &s_is_failed); + + if (!IS_IPv4) { + _device_ip_state_accumulate(priv->ipac6_data.state, + &s_is_started, + &s_is_pending, + &s_is_failed); + } + + v_bool = FALSE; + _device_ip_state_accumulate(priv->ipdhcp_data_x[IS_IPv4].state, + &s_is_started, + &s_is_pending, + &v_bool); + if (v_bool) { + if (!IS_IPv4 && priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) { + /* DHCPv6 is best-effort and not required. */ + } else + s_is_failed = TRUE; + } + + _device_ip_state_accumulate(priv->ipshared_data_x[IS_IPv4].state, + &s_is_started, + &s_is_pending, + &s_is_failed); + + _device_ip_state_accumulate(priv->ipdev_data_x[IS_IPv4].state, + &s_is_started, + &s_is_pending, + &s_is_failed); + + _device_ip_state_accumulate(priv->ipdev_data_unspec.state, + &s_is_started, + &s_is_pending, + &s_is_failed); + + if (s_is_failed) + ip_state = NM_DEVICE_IP_STATE_FAILED; + else if (s_is_pending) + ip_state = NM_DEVICE_IP_STATE_PENDING; + else if (s_is_started) + ip_state = NM_DEVICE_IP_STATE_READY; + else + ip_state = NM_DEVICE_IP_STATE_PENDING; + +got_ip_state: + +#define _state_str_a(state, name) \ + ({ \ + const NMDeviceIPState _state = (state); \ + char *_s = ""; \ + \ + if (_state != NM_DEVICE_IP_STATE_NONE) { \ + _s = nm_sprintf_bufa(NM_STRLEN(name) + 11, \ + " " name "=%s", \ + nm_device_ip_state_to_string(_state)); \ + } \ + _s; \ + }) + + nm_assert(!priv->ip_data_4.is_ignore); + + _LOGT_ip(addr_family, + "check-state: state %s => %s, is_failed=%d, is_pending=%d, is_started=%d, " + "may-fail-4=%d, may-fail-6=%d;" + "%s;%s%s%s%s%s%s;%s%s%s%s%s%s%s%s", + nm_device_ip_state_to_string(priv->ip_data_x[IS_IPv4].state), + nm_device_ip_state_to_string(ip_state), + s_is_failed, + s_is_pending, + s_is_started, + _prop_get_ipvx_may_fail_cached(self, AF_INET, IS_IPv4 ? &may_fail : &may_fail_other), + _prop_get_ipvx_may_fail_cached(self, AF_INET6, !IS_IPv4 ? &may_fail : &may_fail_other), + priv->ip_data_4.is_disabled ? " disabled4" : "", + _state_str_a(priv->ipmanual_data.state_4, "manualip4"), + _state_str_a(priv->ipdev_data_unspec.state, "dev"), + _state_str_a(priv->ipll_data_4.state, "ll4"), + _state_str_a(priv->ipdhcp_data_4.state, "dhcp4"), + _state_str_a(priv->ipdev_data_4.state, "dev4"), + _state_str_a(priv->ipshared_data_4.state, "shared4"), + priv->ip_data_6.is_disabled ? " disabled6" : "", + priv->ip_data_6.is_ignore ? " ignore6" : "", + _state_str_a(priv->ipmanual_data.state_6, "manualip6"), + _state_str_a(priv->ipll_data_6.state, "ll6"), + _state_str_a(priv->ipac6_data.state, "ac6"), + _state_str_a(priv->ipdhcp_data_6.state, "dhcp6"), + _state_str_a(priv->ipdev_data_6.state, "dev6"), + _state_str_a(priv->ipshared_data_6.state, "shared6")); + + if (priv->ip_data_x[IS_IPv4].state == ip_state) { + /* no change. We can stop here. However, we also cancel the pending check, if any, + * because we just determined that there is no change. */ + } else { + _dev_ip_state_set_state(self, addr_family, ip_state, "check-ip-state"); + } + + if (ip_state == NM_DEVICE_IP_STATE_NONE) { + /* Nothing to do. This almost cannot happen, and there is probably nothing + * to do about this case. */ + goto out_done; + } + + ip_state_other = priv->ip_data_x[!IS_IPv4].state; + + if (ip_state == NM_DEVICE_IP_STATE_READY) { + /* we only set NM_ACTIVATION_STATE_FLAG_IP_READY_X() flag once we reach NM_DEVICE_IP_STATE_READY state. + * We don't ever clear it, even if we later enter NM_DEVICE_IP_STATE_FAILED state. + * + * This is not documented/guaranteed behavior, but seems to make sense for now. */ + _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_IP_READY_X(IS_IPv4)); + } + + if (ip_state == NM_DEVICE_IP_STATE_READY && ip_state_other == NM_DEVICE_IP_STATE_READY) + combinedip_state = NM_DEVICE_IP_STATE_READY; + else if (ip_state == NM_DEVICE_IP_STATE_READY && ip_state_other == NM_DEVICE_IP_STATE_PENDING + && disabled_or_ignore) { + /* This IP method is disabled/ignore, but the other family is still pending. + * Regardless of ipvx.may-fail, this means that we always require the other IP family + * to get ready too. */ + combinedip_state = NM_DEVICE_IP_STATE_PENDING; + } else if (ip_state == NM_DEVICE_IP_STATE_READY && ip_state_other == NM_DEVICE_IP_STATE_PENDING + && (priv->ip_data_x[!IS_IPv4].req_timeout_source + || !_prop_get_ipvx_may_fail_cached(self, + nm_utils_addr_family_other(addr_family), + &may_fail_other))) + combinedip_state = NM_DEVICE_IP_STATE_PENDING; + else if (ip_state == NM_DEVICE_IP_STATE_READY + && _prop_get_ipvx_may_fail_cached(self, + nm_utils_addr_family_other(addr_family), + &may_fail_other)) + combinedip_state = NM_DEVICE_IP_STATE_READY; + else if (ip_state == NM_DEVICE_IP_STATE_FAILED + && !_prop_get_ipvx_may_fail_cached(self, addr_family, &may_fail)) + combinedip_state = NM_DEVICE_IP_STATE_FAILED; + else if ((ip_state == NM_DEVICE_IP_STATE_FAILED + || (ip_state == NM_DEVICE_IP_STATE_READY && disabled_or_ignore)) + && (ip_state_other == NM_DEVICE_IP_STATE_FAILED + || (ip_state_other == NM_DEVICE_IP_STATE_READY && disabled_or_ignore_other))) { + /* If both IP states failed, or one failed and the other is disabled + * then it's a failure. may-fail does not mean that both families may + * fail, instead it means that at least one family must succeed. */ + if (nm_device_sys_iface_state_is_external_or_assume(self)) { + _dev_ip_state_set_state(self, AF_INET, NM_DEVICE_IP_STATE_READY, "assumed"); + _dev_ip_state_set_state(self, AF_INET6, NM_DEVICE_IP_STATE_READY, "assumed"); + combinedip_state = NM_DEVICE_IP_STATE_READY; + } else { + combinedip_state = NM_DEVICE_IP_STATE_FAILED; + } + } else { + if (priv->ip_data.state == NM_DEVICE_IP_STATE_NONE) + combinedip_state = NM_DEVICE_IP_STATE_PENDING; + else + combinedip_state = priv->ip_data.state; + } + + _LOGT_ip(AF_UNSPEC, + "check-state: (combined) state %s => %s", + nm_device_ip_state_to_string(priv->ip_data.state), + nm_device_ip_state_to_string(combinedip_state)); + + if (!_dev_ip_state_set_state(self, AF_UNSPEC, combinedip_state, "check-ip-state")) + goto out_done; + + switch (combinedip_state) { + case NM_DEVICE_IP_STATE_PENDING: + break; + case NM_DEVICE_IP_STATE_READY: + _dev_ip_state_req_timeout_cancel(self, AF_UNSPEC); + if (priv->state == NM_DEVICE_STATE_IP_CONFIG) { + nm_device_state_changed(self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + } + break; + case NM_DEVICE_IP_STATE_FAILED: + nm_device_state_changed(self, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + break; + case NM_DEVICE_IP_STATE_NONE: + default: + nm_assert_not_reached(); + } + +out_done: + /* we just checked the state. We can cancel the pending async check. */ + nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].check_async_source); +} + +static gboolean +_dev_ip_state_check_async_cb(NMDevice *self, int addr_family) +{ + _dev_ip_state_check(self, addr_family); + return G_SOURCE_CONTINUE; +} + +static gboolean +_dev_ip_state_check_async_cb_4(gpointer user_data) +{ + return _dev_ip_state_check_async_cb(user_data, AF_INET); +} + +static gboolean +_dev_ip_state_check_async_cb_6(gpointer user_data) +{ + return _dev_ip_state_check_async_cb(user_data, AF_INET6); +} + +static void +_dev_ip_state_check_async(NMDevice *self, int addr_family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int IS_IPv4; + + if (addr_family == AF_UNSPEC) { + _dev_ip_state_check_async(self, AF_INET); + _dev_ip_state_check_async(self, AF_INET6); + return; + } + + IS_IPv4 = NM_IS_IPv4(addr_family); + if (!priv->ip_data_x[IS_IPv4].check_async_source) { + priv->ip_data_x[IS_IPv4].check_async_source = nm_g_idle_add_source( + (IS_IPv4 ? _dev_ip_state_check_async_cb_4 : _dev_ip_state_check_async_cb_6), + self); + } +} + +static void +_dev_ip_state_cleanup(NMDevice *self, int addr_family, gboolean from_reapply) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int IS_IPv4; + + if (addr_family == AF_UNSPEC) { + _dev_ip_state_set_state(self, + addr_family, + from_reapply ? NM_DEVICE_IP_STATE_PENDING : NM_DEVICE_IP_STATE_NONE, + "ip-state-clear"); + return; + } + + IS_IPv4 = NM_IS_IPv4(addr_family); + + nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].check_async_source); + nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].req_timeout_source); + _dev_ip_state_set_state(self, + addr_family, + from_reapply ? NM_DEVICE_IP_STATE_PENDING : NM_DEVICE_IP_STATE_NONE, + "ip-state-clear"); + priv->ip_data_x[IS_IPv4].wait_for_carrier = FALSE; + priv->ip_data_x[IS_IPv4].wait_for_ports = FALSE; + priv->ip_data_x[IS_IPv4].is_disabled = FALSE; + priv->ip_data_x[IS_IPv4].is_ignore = FALSE; + priv->ip_data_x[IS_IPv4].do_reapply = FALSE; +} + +/*****************************************************************************/ + +static gpointer +_dev_l3_config_data_tag_get(NMDevicePrivate *priv, L3ConfigDataType l3cd_type) +{ + nm_assert(_NM_INT_NOT_NEGATIVE(l3cd_type) && l3cd_type < G_N_ELEMENTS(priv->l3cds)); + + return &priv->l3cds[l3cd_type]; +} + +static L3ConfigDataType +_dev_l3_config_data_tag_to_type(NMDevice *self, gconstpointer tag) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int d; + + /* In C it is undefined behavior to compare unrelated pointers. + * Work around that by using nm_ptr_to_uintptr(), which casts the pointers + * to integers. + * + * I guess, theoretically it's still a problem to assume that if tag pointers + * somewhere inside priv->l3cds, that the uintptr_t case would also yield + * a value in that range. In practice, I couldn't imaging this not not work + * reliably. */ + + if (nm_ptr_to_uintptr(tag) < nm_ptr_to_uintptr(&priv->l3cds[0]) + || nm_ptr_to_uintptr(tag) >= nm_ptr_to_uintptr(&priv->l3cds[G_N_ELEMENTS(priv->l3cds)])) + return _L3_CONFIG_DATA_TYPE_NONE; + + d = ((typeof(priv->l3cds[0]) *) tag) - (&priv->l3cds[0]); + + nm_assert(d >= 0); + nm_assert(d < _L3_CONFIG_DATA_TYPE_NUM); + nm_assert(tag == &priv->l3cds[d]); + nm_assert(tag == _dev_l3_config_data_tag_get(priv, d)); + return d; +} + +static L3ConfigDataType +_dev_l3_config_data_acd_addr_info_to_type(NMDevice *self, + const NML3AcdAddrInfo *addr_info, + guint i_track_infos) +{ + nm_assert(NM_IS_DEVICE(self)); + nm_assert(addr_info); + nm_assert(i_track_infos < addr_info->n_track_infos); + + return _dev_l3_config_data_tag_to_type(self, addr_info->track_infos[i_track_infos].tag); +} + +// FIXME(l3cfg): unused function?? +_nm_unused static const NML3AcdAddrTrackInfo * +_dev_l3_config_data_acd_addr_info_has_by_type(NMDevice *self, + const NML3AcdAddrInfo *addr_info, + L3ConfigDataType l3cd_type) +{ + guint i; + + nm_assert(NM_IS_DEVICE(self)); + nm_assert(addr_info); + nm_assert(_NM_INT_NOT_NEGATIVE(l3cd_type) && l3cd_type < _L3_CONFIG_DATA_TYPE_NUM); + + for (i = 0; i < addr_info->n_track_infos; i++) { + if (l3cd_type == _dev_l3_config_data_acd_addr_info_to_type(self, addr_info, i)) + return &addr_info->track_infos[i]; + } + return NULL; +} + +static void +_dev_l3_get_config_settings(NMDevice *self, + L3ConfigDataType type, + NML3ConfigMergeFlags *out_merge_flags, + NML3AcdDefendType *out_acd_defend_type, + guint32 *out_acd_timeout_msec) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NML3ConfigMergeFlags flags; + NMConnection *connection; + NMSettingIPConfig *s_ip; + + nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < _L3_CONFIG_DATA_TYPE_NUM); + + if (G_UNLIKELY(!priv->l3config_merge_flags_has)) { + int IS_IPv4; + + connection = nm_device_get_applied_connection(self); + + for (IS_IPv4 = 0; IS_IPv4 < 2; IS_IPv4++) { + flags = NM_L3_CONFIG_MERGE_FLAGS_NONE; + + if (connection + && (s_ip = nm_connection_get_setting_ip_config(connection, + IS_IPv4 ? AF_INET : AF_INET6))) { + if (nm_setting_ip_config_get_ignore_auto_routes(s_ip)) + flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES; + + if (nm_setting_ip_config_get_ignore_auto_dns(s_ip)) + flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_DNS; + + if (nm_setting_ip_config_get_never_default(s_ip) + || nm_setting_ip_config_get_gateway(s_ip)) { + /* if the connection has an explicit gateway, we also ignore + * the default routes from other sources. */ + flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES; } } + + priv->l3config_merge_flags_x[IS_IPv4] = flags; + } + priv->l3config_merge_flags_has = TRUE; + } + + switch (type) { + case L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC: + case L3_CONFIG_DATA_TYPE_MANUALIP: + case L3_CONFIG_DATA_TYPE_LL_4: + case L3_CONFIG_DATA_TYPE_LL_6: + case L3_CONFIG_DATA_TYPE_PD_6: + case L3_CONFIG_DATA_TYPE_SHARED_4: + case L3_CONFIG_DATA_TYPE_DEVIP_4: + case L3_CONFIG_DATA_TYPE_AC_6: + case L3_CONFIG_DATA_TYPE_DHCP_6: + case L3_CONFIG_DATA_TYPE_DEVIP_6: + *out_acd_timeout_msec = _prop_get_ipv4_dad_timeout(self); + goto after_acd_timeout; + + case L3_CONFIG_DATA_TYPE_DHCP_4: + /* For DHCP, we perform ACD separately, because we want to decline the + * lease in case of a conflict. */ + *out_acd_timeout_msec = 0; + goto after_acd_timeout; + + case _L3_CONFIG_DATA_TYPE_NUM: + case _L3_CONFIG_DATA_TYPE_NONE: + case _L3_CONFIG_DATA_TYPE_ACD_ONLY: + break; + } + *out_acd_timeout_msec = nm_assert_unreachable_val(0); + +after_acd_timeout: + switch (type) { + case L3_CONFIG_DATA_TYPE_LL_4: + *out_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_ONCE; + goto after_acd_defend_type; + + case L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC: + case L3_CONFIG_DATA_TYPE_MANUALIP: + case L3_CONFIG_DATA_TYPE_LL_6: + case L3_CONFIG_DATA_TYPE_PD_6: + case L3_CONFIG_DATA_TYPE_SHARED_4: + case L3_CONFIG_DATA_TYPE_DHCP_4: + case L3_CONFIG_DATA_TYPE_DEVIP_4: + case L3_CONFIG_DATA_TYPE_AC_6: + case L3_CONFIG_DATA_TYPE_DHCP_6: + case L3_CONFIG_DATA_TYPE_DEVIP_6: + *out_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_ALWAYS; + goto after_acd_defend_type; + + case _L3_CONFIG_DATA_TYPE_NUM: + case _L3_CONFIG_DATA_TYPE_NONE: + case _L3_CONFIG_DATA_TYPE_ACD_ONLY: + break; + } + *out_acd_defend_type = nm_assert_unreachable_val(NM_L3_ACD_DEFEND_TYPE_ALWAYS); + +after_acd_defend_type: + switch (type) { + case L3_CONFIG_DATA_TYPE_DEVIP_UNSPEC: + case L3_CONFIG_DATA_TYPE_MANUALIP: + case L3_CONFIG_DATA_TYPE_LL_4: + case L3_CONFIG_DATA_TYPE_LL_6: + case L3_CONFIG_DATA_TYPE_PD_6: + case L3_CONFIG_DATA_TYPE_SHARED_4: + *out_merge_flags = NM_L3_CONFIG_MERGE_FLAGS_NONE; + goto after_merge_flags; + + case L3_CONFIG_DATA_TYPE_DHCP_4: + case L3_CONFIG_DATA_TYPE_DEVIP_4: + *out_merge_flags = priv->l3config_merge_flags_4; + goto after_merge_flags; + + case L3_CONFIG_DATA_TYPE_AC_6: + case L3_CONFIG_DATA_TYPE_DHCP_6: + case L3_CONFIG_DATA_TYPE_DEVIP_6: + *out_merge_flags = priv->l3config_merge_flags_6; + goto after_merge_flags; + + case _L3_CONFIG_DATA_TYPE_NUM: + case _L3_CONFIG_DATA_TYPE_NONE: + case _L3_CONFIG_DATA_TYPE_ACD_ONLY: + break; + } + *out_merge_flags = nm_assert_unreachable_val(NM_L3_CONFIG_MERGE_FLAGS_NONE); + +after_merge_flags: + return; +} + +static gboolean +_dev_l3_register_l3cds_add_config(NMDevice *self, + L3ConfigDataType l3cd_type, + NML3CfgConfigFlags flags) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NML3ConfigMergeFlags merge_flags; + NML3AcdDefendType acd_defend_type; + guint32 acd_timeout_msec; + + _dev_l3_get_config_settings(self, l3cd_type, &merge_flags, &acd_defend_type, &acd_timeout_msec); + return nm_l3cfg_add_config(priv->l3cfg, + _dev_l3_config_data_tag_get(priv, l3cd_type), + FALSE, + priv->l3cds[l3cd_type].d, + l3cd_type, + nm_device_get_route_table(self, AF_INET), + nm_device_get_route_table(self, AF_INET6), + nm_device_get_route_metric(self, AF_INET), + nm_device_get_route_metric(self, AF_INET6), + _dev_default_route_metric_penalty_get(self, AF_INET), + _dev_default_route_metric_penalty_get(self, AF_INET6), + _prop_get_ipvx_dns_priority(self, AF_INET), + _prop_get_ipvx_dns_priority(self, AF_INET6), + acd_defend_type, + acd_timeout_msec, + flags, + merge_flags); +} + +static gboolean +_dev_l3_register_l3cds_set_one_full(NMDevice *self, + L3ConfigDataType l3cd_type, + const NML3ConfigData *l3cd, + NML3CfgConfigFlags flags, + NMTernary commit_sync) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; + gboolean changed = FALSE; + + if (priv->l3cds[l3cd_type].d != l3cd) { + if (nm_l3_config_data_equal(priv->l3cds[l3cd_type].d, l3cd)) { + /* we would set to a different instance, but the same content! + * We keep the previous one and ignore the new @l3cd. + * + * Warning: this means, that after calling this function, + * priv->l3cds[l3cd_type].d still might point to a different + * (though semantically equal) l3cd instance. */ + } else { + l3cd_old = g_steal_pointer(&priv->l3cds[l3cd_type].d); + if (l3cd) + priv->l3cds[l3cd_type].d = nm_l3_config_data_ref_and_seal(l3cd); + } + } + + if (priv->l3cfg) { + if (priv->l3cds[l3cd_type].d) { + if (_dev_l3_register_l3cds_add_config(self, l3cd_type, flags)) + changed = TRUE; + } + + if (l3cd_old) { + if (nm_l3cfg_remove_config(priv->l3cfg, + _dev_l3_config_data_tag_get(priv, l3cd_type), + l3cd_old)) + changed = TRUE; } } - if (priv->ip_state_x[IS_IPv4] == new_state) + if (changed && commit_sync != NM_TERNARY_DEFAULT) + _dev_l3_cfg_commit(self, !!commit_sync); + + return changed; +} + +static gboolean +_dev_l3_register_l3cds_set_one(NMDevice *self, + L3ConfigDataType l3cd_type, + const NML3ConfigData *l3cd, + NMTernary commit_sync) +{ + return _dev_l3_register_l3cds_set_one_full(self, + l3cd_type, + l3cd, + NM_L3CFG_CONFIG_FLAGS_NONE, + commit_sync); +} + +static void +_dev_l3_update_l3cds_ifindex(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int ip_ifindex; + int i; + + ip_ifindex = nm_device_get_ip_ifindex(self); + if (ip_ifindex <= 0) return; - _LOGT(LOGD_DEVICE, - "ip%c-state: set to %d (%s)", - nm_utils_addr_family_to_char(addr_family), - (int) new_state, - nm_device_ip_state_to_string(new_state)); + for (i = 0; i < (int) G_N_ELEMENTS(priv->l3cds); i++) { + if (priv->l3cds[i].d && nm_l3_config_data_get_ifindex(priv->l3cds[i].d) != ip_ifindex) { + nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; - priv->ip_state_x_[IS_IPv4] = new_state; + l3cd_old = g_steal_pointer(&priv->l3cds[i].d); - if (new_state == NM_DEVICE_IP_STATE_DONE) { - /* we only set the IPx_READY flag once we reach NM_DEVICE_IP_STATE_DONE state. We don't - * ever clear it, even if we later enter NM_DEVICE_IP_STATE_FAIL state. - * - * This is not documented/guaranteed behavior, but seems to make sense for now. */ - _active_connection_set_state_flags(self, - NM_IS_IPv4(addr_family) - ? NM_ACTIVATION_STATE_FLAG_IP4_READY - : NM_ACTIVATION_STATE_FLAG_IP6_READY); + priv->l3cds[i].d = + nm_l3_config_data_seal(nm_l3_config_data_new_clone(l3cd_old, ip_ifindex)); + } } } +static gboolean +_dev_l3_register_l3cds(NMDevice *self, + NML3Cfg *l3cfg, + gboolean do_add /* else remove */, + NMTernary do_commit) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gboolean is_external; + gboolean changed; + int i; + + if (!l3cfg) + return FALSE; + + is_external = nm_device_sys_iface_state_is_external(self); + + changed = FALSE; + for (i = 0; i < (int) G_N_ELEMENTS(priv->l3cds); i++) { + if (!priv->l3cds[i].d) + continue; + if (!do_add) { + if (nm_l3cfg_remove_config(l3cfg, + _dev_l3_config_data_tag_get(priv, i), + priv->l3cds[i].d)) + changed = TRUE; + continue; + } + if (is_external) + continue; + if (_dev_l3_register_l3cds_add_config(self, i, NM_L3CFG_CONFIG_FLAGS_NONE)) + changed = TRUE; + } + + if (do_commit == NM_TERNARY_DEFAULT) + do_commit = changed; + if (do_commit) + _dev_l3_cfg_commit(self, TRUE); + + return changed; +} + +/*****************************************************************************/ + +void +nm_device_l3cfg_commit(NMDevice *self, NML3CfgCommitType commit_type, gboolean commit_sync) +{ + NMDevicePrivate *priv; + + g_return_if_fail(NM_IS_DEVICE(self)); + + priv = NM_DEVICE_GET_PRIVATE(self); + + if (!priv->l3cfg) + return; + + /* FIXME(l3cfg): commit_sync should go away and not be used. The reason is that + * a commit does *a lot* of things which are outside the control of the caller, + * which makes it unsuitable to call in most cases. */ + if (!commit_sync) { + nm_l3cfg_commit_on_idle_schedule(priv->l3cfg, commit_type); + return; + } + + nm_l3cfg_commit(priv->l3cfg, commit_type); +} + +static void +_dev_l3_cfg_commit(NMDevice *self, gboolean commit_sync) +{ + nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_AUTO, commit_sync); +} + +static void +update_external_connection(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMSettingsConnection *settings_connection; + gs_unref_object NMConnection *connection_new = NULL; + NMConnection *connection_old; + gs_unref_object NMSetting *s_ip4_new = NULL; + gs_unref_object NMSetting *s_ip6_new = NULL; + NMSetting *s_ip4_old; + NMSetting *s_ip6_old; + + /* Update external connections with configuration from platform */ + + if (!nm_device_sys_iface_state_is_external(self)) + return; + + settings_connection = nm_device_get_settings_connection(self); + if (!settings_connection) + return; + + if (!NM_FLAGS_HAS(nm_settings_connection_get_flags(settings_connection), + NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) + return; + + if (nm_active_connection_get_activation_type(NM_ACTIVE_CONNECTION(priv->act_request.obj)) + != NM_ACTIVATION_TYPE_EXTERNAL) + return; + + connection_old = nm_settings_connection_get_connection(settings_connection); + s_ip4_old = nm_connection_get_setting(connection_old, NM_TYPE_SETTING_IP4_CONFIG); + s_ip6_old = nm_connection_get_setting(connection_old, NM_TYPE_SETTING_IP6_CONFIG); + + s_ip4_new = nm_utils_platform_capture_ip_setting(nm_device_get_platform(self), + AF_INET, + nm_device_get_ip_ifindex(self), + FALSE); + s_ip6_new = nm_utils_platform_capture_ip_setting(nm_device_get_platform(self), + AF_INET6, + nm_device_get_ip_ifindex(self), + _get_maybe_ipv6_disabled(self)); + + if (!s_ip4_old || !nm_setting_compare(s_ip4_new, s_ip4_old, NM_SETTING_COMPARE_FLAG_EXACT)) { + connection_new = nm_simple_connection_new_clone(connection_old); + nm_connection_add_setting(connection_new, g_steal_pointer(&s_ip4_new)); + } + + if (!s_ip6_old || !nm_setting_compare(s_ip6_new, s_ip6_old, NM_SETTING_COMPARE_FLAG_EXACT)) { + if (!connection_new) + connection_new = nm_simple_connection_new_clone(connection_old); + nm_connection_add_setting(connection_new, g_steal_pointer(&s_ip6_new)); + } + + if (connection_new) { + nm_settings_connection_update(settings_connection, + connection_new, + NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY, + NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, + NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, + NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET, + "update-external", + NULL); + } +} + +static void +_dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + nm_assert(l3cfg == priv->l3cfg); + + switch (notify_data->notify_type) { + case NM_L3_CONFIG_NOTIFY_TYPE_L3CD_CHANGED: + if (notify_data->l3cd_changed.commited) { + g_signal_emit(self, + signals[L3CD_CHANGED], + 0, + notify_data->l3cd_changed.l3cd_old, + notify_data->l3cd_changed.l3cd_new); + } + return; + case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT: + { + const NML3AcdAddrInfo *addr_info = ¬ify_data->acd_event.info; + + if (addr_info->state > NM_L3_ACD_ADDR_STATE_PROBING) + _dev_ipmanual_check_ready(self); + return; + } + case NM_L3_CONFIG_NOTIFY_TYPE_PRE_COMMIT: + { + const NML3ConfigData *l3cd; + + /* FIXME(l3cfg): MTU handling should be moved to l3cfg. */ + l3cd = nm_l3cfg_get_combined_l3cd(l3cfg, TRUE); + if (l3cd) + priv->ip6_mtu = nm_l3_config_data_get_ip6_mtu(l3cd); + _commit_mtu(self); + return; + } + case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT: + if (priv->ipshared_data_4.state == NM_DEVICE_IP_STATE_PENDING + && !priv->ipshared_data_4.v4.dnsmasq_manager && priv->ipshared_data_4.v4.l3cd) { + _dev_ipshared4_spawn_dnsmasq(self); + nm_clear_l3cd(&priv->ipshared_data_4.v4.l3cd); + } + _dev_ipmanual_check_ready(self); + return; + case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT: + nm_assert(NM_IS_L3_IPV4LL(notify_data->ipv4ll_event.ipv4ll)); + if (priv->ipll_data_4.v4.ipv4ll == notify_data->ipv4ll_event.ipv4ll) + _dev_ipll4_notify_event(self); + return; + case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE: + return; + case NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED: + /* we commit again. This way we try to configure the routes.*/ + _dev_l3_cfg_commit(self, FALSE); + return; + case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE: + if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags, + nmp_object_type_to_flags(NMP_OBJECT_TYPE_LINK) + | nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP4_ADDRESS) + | nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ADDRESS))) + _dev_unmanaged_check_external_down(self, TRUE, TRUE); + + if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags, + nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP4_ADDRESS) + | nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ADDRESS))) { + g_signal_emit(self, signals[PLATFORM_ADDRESS_CHANGED], 0); + } + + /* Check if AC6 addresses completed DAD */ + if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags, + nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ADDRESS)) + && priv->ipac6_data.state == NM_DEVICE_IP_STATE_PENDING && priv->ipac6_data.l3cd + && nm_l3cfg_check_ready(l3cfg, + priv->ipac6_data.l3cd, + AF_INET6, + NM_L3CFG_CHECK_READY_FLAGS_IP6_DAD_READY, + NULL)) { + nm_clear_l3cd(&priv->ipac6_data.l3cd); + _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_READY); + _dev_ip_state_check_async(self, AF_INET6); + } + + _dev_ipmanual_check_ready(self); + update_external_connection(self); + nm_device_queue_recheck_assume(self); + return; + + case _NM_L3_CONFIG_NOTIFY_TYPE_NUM: + break; + } + nm_assert_not_reached(); +} + +static void +_dev_l3_cfg_commit_type_reset(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NML3CfgCommitType commit_type; + + if (!priv->l3cfg) + return; + + switch (priv->sys_iface_state) { + case NM_DEVICE_SYS_IFACE_STATE_EXTERNAL: + case NM_DEVICE_SYS_IFACE_STATE_REMOVED: + commit_type = NM_L3_CFG_COMMIT_TYPE_NONE; + goto do_set; + case NM_DEVICE_SYS_IFACE_STATE_ASSUME: + commit_type = NM_L3_CFG_COMMIT_TYPE_ASSUME; + goto do_set; + case NM_DEVICE_SYS_IFACE_STATE_MANAGED: + commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE; + goto do_set; + } + nm_assert_not_reached(); + return; + +do_set: + priv->l3cfg_commit_type = + nm_l3cfg_commit_type_register(priv->l3cfg, commit_type, priv->l3cfg_commit_type, "device"); + if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE) + nm_l3cfg_commit_type_reset_update(priv->l3cfg); +} + /*****************************************************************************/ const char * @@ -2973,11 +4000,18 @@ nm_device_get_iface(NMDevice *self) static gboolean _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - int * p_ifindex; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gs_unref_object NML3Cfg *l3cfg_old = NULL; + NML3CfgCommitTypeHandle *l3cfg_commit_type_old = NULL; + gboolean l3_changed; + int ip_ifindex_new; + int *p_ifindex; + gboolean l3cfg_was_reset = FALSE; - if (ifindex < 0) + if (ifindex < 0) { + nm_assert_not_reached(); ifindex = 0; + } p_ifindex = is_ip_ifindex ? &priv->ip_ifindex_ : &priv->ifindex_; @@ -2986,13 +4020,108 @@ _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex) *p_ifindex = ifindex; - _LOGD(LOGD_DEVICE, "ifindex: set %sifindex %d", is_ip_ifindex ? "ip-" : "", ifindex); + ip_ifindex_new = nm_device_get_ip_ifindex(self); - if (!is_ip_ifindex) - _notify(self, PROP_IFINDEX); + if (priv->l3cfg) { + if (ip_ifindex_new <= 0 || ip_ifindex_new != nm_l3cfg_get_ifindex(priv->l3cfg)) { + const NML3ConfigData *l3cd_old; + + if (ip_ifindex_new <= 0) { + /* The ifindex was reset. Send a last L3CD_CHANGED + * signal with a NULL l3cd so that the old one can + * be removed from the DNS manager. + */ + l3cd_old = nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE); + if (l3cd_old) + g_signal_emit(self, signals[L3CD_CHANGED], 0, l3cd_old, NULL); + } + + g_signal_handlers_disconnect_by_func(priv->l3cfg, + G_CALLBACK(_dev_l3_cfg_notify_cb), + self); + l3cfg_old = g_steal_pointer(&priv->l3cfg_); + l3cfg_commit_type_old = g_steal_pointer(&priv->l3cfg_commit_type); + l3cfg_was_reset = TRUE; + } + } + if (!priv->l3cfg && ip_ifindex_new > 0) { + priv->l3cfg_ = nm_netns_l3cfg_acquire(priv->netns, ip_ifindex_new); + + g_signal_connect(priv->l3cfg, + NM_L3CFG_SIGNAL_NOTIFY, + G_CALLBACK(_dev_l3_cfg_notify_cb), + self); + + _dev_l3_cfg_commit_type_reset(self); + l3cfg_was_reset = TRUE; + } + if (!priv->l3cfg) { + _cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_KEEP, FALSE); + _cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_KEEP, FALSE); + } + + _LOGD(LOGD_DEVICE, + "ifindex: set %sifindex %d%s%s%s%s%s%s", + is_ip_ifindex ? "ip-" : "", + ifindex, + NM_PRINT_FMT_QUOTED(l3cfg_old && l3cfg_old != priv->l3cfg, + " (old-l3cfg: ", + nm_hash_obfuscated_ptr_str_a(l3cfg_old), + ")", + ""), + NM_PRINT_FMT_QUOTED(priv->l3cfg && l3cfg_old != priv->l3cfg, + " (l3cfg: ", + nm_hash_obfuscated_ptr_str_a(priv->l3cfg), + ")", + "")); if (priv->manager) nm_manager_emit_device_ifindex_changed(priv->manager, self); + + if (!is_ip_ifindex) + _notify(self, PROP_IFINDEX); + + if (l3cfg_was_reset) { + gs_unref_object NMIPConfig *ipconf_old_4 = NULL; + gs_unref_object NMIPConfig *ipconf_old_6 = NULL; + + ipconf_old_4 = g_steal_pointer(&priv->l3ipdata_4.ip_config); + ipconf_old_6 = g_steal_pointer(&priv->l3ipdata_6.ip_config); + if (priv->l3cfg) { + priv->l3ipdata_4.ip_config = nm_l3cfg_ipconfig_acquire(priv->l3cfg, AF_INET); + priv->l3ipdata_6.ip_config = nm_l3cfg_ipconfig_acquire(priv->l3cfg, AF_INET6); + } + _notify(self, PROP_IP4_CONFIG); + _notify(self, PROP_IP6_CONFIG); + } + + if (l3cfg_old != priv->l3cfg) { + l3_changed = FALSE; + if (_dev_l3_register_l3cds(self, l3cfg_old, FALSE, FALSE)) + l3_changed = TRUE; + + /* Now it gets ugly. We changed the ip-ifindex, which determines the NML3Cfg instance. + * But all the NML3ConfigData we currently track are still for the old ifindex. We + * need to update them. + * + * This should be all handled entirely different, where an NMDevice is strictly + * associated with one ifindex (and not the ifindex/ip-ifindex split). Or it + * is not at all associated with an ifindex, but only a controlling device for + * a real NMDevice (that has the ifindex). */ + _dev_l3_update_l3cds_ifindex(self); + + if (_dev_l3_register_l3cds(self, priv->l3cfg, TRUE, FALSE)) + l3_changed = TRUE; + + if (l3_changed) + _dev_l3_cfg_commit(self, TRUE); + } + + if (l3cfg_commit_type_old) + nm_l3cfg_commit_type_unregister(l3cfg_old, l3cfg_commit_type_old); + + update_prop_ip_iface(self); + return TRUE; } @@ -3013,9 +4142,9 @@ _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex) gboolean nm_device_take_over_link(NMDevice *self, int ifindex, char **old_name, GError **error) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const NMPlatformLink *plink; - NMPlatform * platform; + NMPlatform *platform; nm_assert(ifindex > 0); NM_SET_OUT(old_name, NULL); @@ -3140,7 +4269,7 @@ static void _set_ip_ifindex(NMDevice *self, int ifindex, const char *ifname) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMPlatform * platform; + NMPlatform *platform; gboolean eq_name; /* normalize arguments */ @@ -3159,13 +4288,12 @@ _set_ip_ifindex(NMDevice *self, int ifindex, const char *ifname) NM_PRINT_FMT_QUOTE_STRING(ifname), ifindex); - _set_ifindex(self, ifindex, TRUE); - if (!eq_name) { g_free(priv->ip_iface_); priv->ip_iface_ = g_strdup(ifname); - _notify(self, PROP_IP_IFACE); + update_prop_ip_iface(self); } + _set_ifindex(self, ifindex, TRUE); if (priv->ip_ifindex > 0) { platform = nm_device_get_platform(self); @@ -3265,10 +4393,10 @@ parent_changed_notify(NMDevice *self, static gboolean _parent_set_ifindex(NMDevice *self, int parent_ifindex, gboolean force_check) { - NMDevicePrivate *priv; - NMDevice * parent_device; - gboolean changed = FALSE; - int old_ifindex; + NMDevicePrivate *priv; + NMDevice *parent_device; + gboolean changed = FALSE; + int old_ifindex; gs_unref_object NMDevice *old_device = NULL; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); @@ -3359,7 +4487,7 @@ const char * nm_device_parent_find_for_connection(NMDevice *self, const char *current_setting_parent) { const char *new_parent; - NMDevice * parent_device; + NMDevice *parent_device; parent_device = nm_device_parent_get_device(self); if (!parent_device) @@ -3496,10 +4624,10 @@ _stats_set_refresh_rate(NMDevice *self, guint refresh_rate_ms) static gboolean get_ip_iface_identifier(NMDevice *self, NMUtilsIPv6IfaceId *out_iid) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMPlatform * platform = nm_device_get_platform(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMPlatform *platform = nm_device_get_platform(self); const NMPlatformLink *pllink; - const guint8 * hwaddr; + const guint8 *hwaddr; guint8 pseudo_hwaddr[ETH_ALEN]; gsize hwaddr_len; int ifindex; @@ -3560,6 +4688,7 @@ get_ip_iface_identifier(NMDevice *self, NMUtilsIPv6IfaceId *out_iid) * @self: an #NMDevice * @iid: where to place the interface identifier * @ignore_token: force creation of a non-tokenized address + * @out_is_token: on return, whether the identifier is tokenized * * Return the interface's identifier for the EUI64 address generation mode. * It's either a manually set token or and identifier generated in a @@ -3571,19 +4700,26 @@ get_ip_iface_identifier(NMDevice *self, NMUtilsIPv6IfaceId *out_iid) * Returns: #TRUE if the @iid could be set */ static gboolean -nm_device_get_ip_iface_identifier(NMDevice *self, NMUtilsIPv6IfaceId *iid, gboolean ignore_token) +nm_device_get_ip_iface_identifier(NMDevice *self, + NMUtilsIPv6IfaceId *iid, + gboolean ignore_token, + gboolean *out_is_token) { NMSettingIP6Config *s_ip6; - const char * token = NULL; + const char *token = NULL; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); + NM_SET_OUT(out_is_token, FALSE); + if (!ignore_token) { s_ip6 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG); g_return_val_if_fail(s_ip6, FALSE); token = nm_setting_ip6_config_get_token(s_ip6); + if (token) + NM_SET_OUT(out_is_token, TRUE); } if (token) return nm_utils_ipv6_interface_identifier_get_from_token(iid, token); @@ -3729,29 +4865,16 @@ nm_device_get_route_metric_default(NMDeviceType device_type) return 11000; } -static gboolean -default_route_metric_penalty_detect(NMDevice *self, int addr_family) +static guint32 +_dev_default_route_metric_penalty_get(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const int IS_IPv4 = NM_IS_IPv4(addr_family); - /* currently we don't differentiate between IPv4 and IPv6 when detecting - * connectivity. */ if (priv->concheck_x[IS_IPv4].state != NM_CONNECTIVITY_FULL && nm_connectivity_check_enabled(concheck_get_mgr(self))) - return TRUE; - - return FALSE; -} - -static guint32 -default_route_metric_penalty_get(NMDevice *self, int addr_family) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - if (NM_IS_IPv4(addr_family) ? priv->default_route_metric_penalty_ip4_has - : priv->default_route_metric_penalty_ip6_has) return 20000; + return 0; } @@ -3760,8 +4883,8 @@ nm_device_get_route_metric(NMDevice *self, int addr_family) { gint64 route_metric; NMSettingIPConfig *s_ip; - NMConnection * connection; - const char * property; + NMConnection *connection; + const char *property; g_return_val_if_fail(NM_IS_DEVICE(self), G_MAXUINT32); g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), G_MAXUINT32); @@ -3813,28 +4936,23 @@ nm_device_get_route_table(NMDevice *self, int addr_family) return route_table ?: (guint32) RT_TABLE_MAIN; } -static NMIPRouteTableSyncMode +/* FIXME(l3cfg): need to properly handle the route-table sync mode and + * use it during commit. */ +_nm_unused static NMIPRouteTableSyncMode _get_route_table_sync_mode_stateful(NMDevice *self, int addr_family) { - const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMDedupMultiIter ipconf_iter; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean all_sync_now; gboolean all_sync_eff; all_sync_now = _prop_get_ipvx_route_table(self, addr_family) != 0u; if (!all_sync_now) { - const NMPlatformIPRoute *route; + const NML3ConfigData *l3cd = priv->l3cds[L3_CONFIG_DATA_TYPE_MANUALIP].d; /* If there's a local route switch to all-sync in order * to properly manage the local table */ - nm_ip_config_iter_ip_route_for_each (&ipconf_iter, priv->con_ip_config_x[IS_IPv4], &route) { - if (nm_platform_route_type_uncoerce(route->type_coerced) == RTN_LOCAL) { - all_sync_now = TRUE; - break; - } - } + all_sync_now = l3cd && nm_l3_config_data_has_routes_with_type_local(l3cd, addr_family); } if (all_sync_now) @@ -3866,18 +4984,20 @@ nm_device_get_best_default_route(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - switch (addr_family) { - case AF_INET: - return priv->ip_config_4 ? nm_ip4_config_best_default_route_get(priv->ip_config_4) : NULL; - case AF_INET6: - return priv->ip_config_6 ? nm_ip6_config_best_default_route_get(priv->ip_config_6) : NULL; - case AF_UNSPEC: - return (priv->ip_config_4 ? nm_ip4_config_best_default_route_get(priv->ip_config_4) : NULL) - ?: (priv->ip_config_6 ? nm_ip6_config_best_default_route_get(priv->ip_config_6) - : NULL); - default: - g_return_val_if_reached(NULL); - } + if (!priv->l3cfg) + return NULL; + + /* FIXME(l3cfg): this function returns the best default route that we + * *want* to configure. What is the meaning of that? Possibly the caller + * cares whether there *is* a default route configured, for which they + * should ask platform. + * + * Check callers why they call this. Quite possibly this whole notion of + * "has a default route" is wrong to being with, regardless whether we + * look at the desired or actual configuration. That is, because "has a default route" + * does not do justice to the complexity of routing (with policy routing, + * etc.). */ + return nm_l3cfg_get_best_default_route(priv->l3cfg, addr_family, TRUE); } const char * @@ -3982,7 +5102,7 @@ NMConnection * nm_device_get_settings_connection_get_connection(NMDevice *self) { NMSettingsConnection *sett_con; - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); if (!priv->act_request.obj) return NULL; @@ -4055,7 +5175,7 @@ typedef enum { CONCHECK_SCHEDULE_RETURNED_MAX, } ConcheckScheduleMode; -static NMDeviceConnectivityHandle *concheck_start(NMDevice * self, +static NMDeviceConnectivityHandle *concheck_start(NMDevice *self, int addr_family, NMDeviceConnectivityCallback callback, gpointer user_data, @@ -4361,7 +5481,7 @@ nm_device_check_connectivity_update_interval(NMDevice *self) } static void -concheck_update_state(NMDevice * self, +concheck_update_state(NMDevice *self, int addr_family, NMConnectivityState state, gboolean allow_periodic_bump) @@ -4432,22 +5552,16 @@ concheck_update_state(NMDevice * self, _notify(self, IS_IPv4 ? PROP_IP4_CONNECTIVITY : PROP_IP6_CONNECTIVITY); - if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_sys_iface_state_is_external(self)) { - if (nm_device_get_best_default_route(self, AF_INET) - && !ip_config_merge_and_apply(self, AF_INET, TRUE)) - _LOGW(LOGD_IP4, "Failed to update IPv4 route metric"); - if (nm_device_get_best_default_route(self, AF_INET6) - && !ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "Failed to update IPv6 route metric"); - } + if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_sys_iface_state_is_external(self)) + _dev_l3_register_l3cds(self, priv->l3cfg, TRUE, NM_TERNARY_DEFAULT); } static const char * nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family) { NMDeviceClass *klass; - NMConnection * connection = nm_device_get_applied_connection(self); - const char * method; + NMConnection *connection = nm_device_get_applied_connection(self); + const char *method; const int IS_IPv4 = NM_IS_IPv4(addr_family); g_return_val_if_fail(NM_IS_CONNECTION(connection), "" /* bogus */); @@ -4494,16 +5608,16 @@ concheck_handle_complete(NMDeviceConnectivityHandle *handle, GError *error) } static void -concheck_cb(NMConnectivity * connectivity, +concheck_cb(NMConnectivity *connectivity, NMConnectivityCheckHandle *c_handle, NMConnectivityState state, gpointer user_data) { _nm_unused gs_unref_object NMDevice *self_keep_alive = NULL; - NMDevice * self; - NMDevicePrivate * priv; - NMDeviceConnectivityHandle * handle; - NMDeviceConnectivityHandle * other_handle; + NMDevice *self; + NMDevicePrivate *priv; + NMDeviceConnectivityHandle *handle; + NMDeviceConnectivityHandle *other_handle; gboolean handle_is_alive; gboolean allow_periodic_bump; gboolean any_periodic_before; @@ -4627,16 +5741,16 @@ check_handles: } static NMDeviceConnectivityHandle * -concheck_start(NMDevice * self, +concheck_start(NMDevice *self, int addr_family, NMDeviceConnectivityCallback callback, gpointer user_data, gboolean is_periodic) { static guint64 seq_counter = 0; - NMDevicePrivate * priv; + NMDevicePrivate *priv; NMDeviceConnectivityHandle *handle; - const char * ifname; + const char *ifname; g_return_val_if_fail(NM_IS_DEVICE(self), NULL); @@ -4692,7 +5806,7 @@ concheck_start(NMDevice * self, } NMDeviceConnectivityHandle * -nm_device_check_connectivity(NMDevice * self, +nm_device_check_connectivity(NMDevice *self, int addr_family, NMDeviceConnectivityCallback callback, gpointer user_data) @@ -4748,8 +5862,8 @@ static SlaveInfo * find_slave_info(NMDevice *self, NMDevice *slave) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - CList * iter; - SlaveInfo * info; + CList *iter; + SlaveInfo *info; c_list_for_each (iter, &priv->slaves) { info = c_list_entry(iter, SlaveInfo, lst_slave); @@ -4774,16 +5888,14 @@ find_slave_info(NMDevice *self, NMDevice *slave) static gboolean nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *connection) { - NMDevicePrivate *priv; - SlaveInfo * info; - gboolean success = FALSE; - gboolean configure; + SlaveInfo *info; + gboolean success = FALSE; + gboolean configure; g_return_val_if_fail(self != NULL, FALSE); g_return_val_if_fail(slave != NULL, FALSE); g_return_val_if_fail(NM_DEVICE_GET_CLASS(self)->enslave_slave != NULL, FALSE); - priv = NM_DEVICE_GET_PRIVATE(self); info = find_slave_info(self, slave); if (!info) return FALSE; @@ -4806,22 +5918,17 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co */ nm_device_update_hw_address(self); + /* Since slave devices don't have their own IP configuration, + * set the MTU here. + */ + _commit_mtu(slave); + /* Restart IP configuration if we're waiting for slaves. Do this * after updating the hardware address as IP config may need the * new address. */ - if (success) { - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_WAIT) - nm_device_activate_stage3_ip_start(self, AF_INET); - - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_WAIT) - nm_device_activate_stage3_ip_start(self, AF_INET6); - } - - /* Since slave devices don't have their own IP configuration, - * set the MTU here. - */ - _commit_mtu(slave, NM_DEVICE_GET_PRIVATE(slave)->ip_config_4); + if (success) + nm_device_activate_schedule_stage3_ip_config(self, FALSE); return success; } @@ -4840,15 +5947,15 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co * updates the state of @self and @slave to reflect its release. */ static void -nm_device_master_release_one_slave(NMDevice * self, - NMDevice * slave, +nm_device_master_release_one_slave(NMDevice *self, + NMDevice *slave, gboolean configure, gboolean force, NMDeviceStateReason reason) { - NMDevicePrivate *priv; - NMDevicePrivate *slave_priv; - SlaveInfo * info; + NMDevicePrivate *priv; + NMDevicePrivate *slave_priv; + SlaveInfo *info; gs_unref_object NMDevice *self_free = NULL; g_return_if_fail(NM_DEVICE(self)); @@ -4908,6 +6015,8 @@ nm_device_master_release_one_slave(NMDevice * self, NM_DEVICE_STATE_REASON_REMOVED); } +/*****************************************************************************/ + /** * can_unmanaged_external_down: * @self: the device @@ -4922,7 +6031,7 @@ can_unmanaged_external_down(NMDevice *self) } static NMUnmanFlagOp -is_unmanaged_external_down(NMDevice *self, gboolean consider_can) +_dev_unmanaged_is_external_down(NMDevice *self, gboolean consider_can) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -4939,7 +6048,7 @@ is_unmanaged_external_down(NMDevice *self, gboolean consider_can) } static void -set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged) +_dev_unmanaged_check_external_down(NMDevice *self, gboolean only_if_unmanaged, gboolean now) { NMUnmanFlagOp ext_flags; @@ -4951,7 +6060,7 @@ set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged) return; } - ext_flags = is_unmanaged_external_down(self, FALSE); + ext_flags = _dev_unmanaged_is_external_down(self, FALSE); if (ext_flags != NM_UNMAN_FLAG_OP_SET_UNMANAGED) { /* Ensure the assume check is queued before any queued state changes * from the transition to UNAVAILABLE. @@ -4959,10 +6068,17 @@ set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged) nm_device_queue_recheck_assume(self); } - nm_device_set_unmanaged_by_flags(self, - NM_UNMANAGED_EXTERNAL_DOWN, - ext_flags, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + if (now) { + nm_device_set_unmanaged_by_flags(self, + NM_UNMANAGED_EXTERNAL_DOWN, + ext_flags, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } else { + nm_device_set_unmanaged_by_flags_queue(self, + NM_UNMANAGED_EXTERNAL_DOWN, + ext_flags, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } } void @@ -4979,26 +6095,15 @@ nm_device_update_dynamic_ip_setup(NMDevice *self) g_hash_table_remove_all(priv->ip6_saved_properties); - if (priv->dhcp_data_4.client) { - if (!nm_device_dhcp4_renew(self, FALSE)) { - nm_device_state_changed(self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_DHCP_FAILED); - return; - } - } - if (priv->dhcp_data_6.client) { - if (!nm_device_dhcp6_renew(self, FALSE)) { - nm_device_state_changed(self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_DHCP_FAILED); - return; - } - } - if (priv->ndisc) { + if (priv->ipdhcp_data_4.state != NM_DEVICE_IP_STATE_NONE) + _dev_ipdhcpx_restart(self, AF_INET, FALSE); + if (priv->ipdhcp_data_6.state != NM_DEVICE_IP_STATE_NONE) + _dev_ipdhcpx_restart(self, AF_INET6, FALSE); + + if (priv->ipac6_data.ndisc) { /* FIXME: todo */ } - if (priv->dnsmasq_manager) { + if (priv->ipshared_data_4.v4.dnsmasq_manager) { /* FIXME: todo */ } } @@ -5033,10 +6138,8 @@ carrier_changed(NMDevice *self, gboolean carrier) nm_device_update_dynamic_ip_setup(self); /* If needed, also resume IP configuration that is * waiting for carrier. */ - if (nm_device_activate_ip4_state_in_wait(self)) - nm_device_activate_stage3_ip_start(self, AF_INET); - if (nm_device_activate_ip6_state_in_wait(self)) - nm_device_activate_stage3_ip_start(self, AF_INET6); + if (priv->state == NM_DEVICE_STATE_IP_CONFIG) + nm_device_activate_schedule_stage3_ip_config(self, FALSE); return; } /* fall-through and change state of device */ @@ -5082,7 +6185,7 @@ carrier_changed(NMDevice *self, gboolean carrier) static gboolean carrier_disconnected_action_cb(gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); + NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); _LOGD(LOGD_DEVICE, @@ -5134,10 +6237,6 @@ nm_device_set_carrier(NMDevice *self, gboolean carrier) nm_device_remove_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); _carrier_wait_check_queued_act_request(self); } - - /* Send ARP announcements if did not yet and have carrier. */ - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !priv->acd.announcing) - nm_device_arp_announce(self); } else { if (priv->carrier_wait_id) nm_device_add_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE); @@ -5188,10 +6287,10 @@ nm_device_set_carrier_from_platform(NMDevice *self) static void device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMDevice * master; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDevice *master; nm_auto_nmpobj const NMPObject *plink_master_keep_alive = NULL; - const NMPlatformLink * plink_master; + const NMPlatformLink *plink_master; g_return_if_fail(plink); @@ -5269,88 +6368,9 @@ device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice } static void -ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gs_unref_array GArray *addresses = NULL; - gs_unref_array GArray *dns_servers = NULL; - gs_unref_array GArray * dns_domains = NULL; - guint len; - guint i; - const NMDedupMultiHeadEntry *head_entry; - NMDedupMultiIter ipconf_iter; - - if (nm_ndisc_get_node_type(ndisc) != NM_NDISC_NODE_TYPE_ROUTER) - return; - - head_entry = nm_ip6_config_lookup_addresses(priv->ip_config_6); - addresses = - g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscAddress), head_entry ? head_entry->len : 0); - nm_dedup_multi_iter_for_each (&ipconf_iter, head_entry) { - const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(ipconf_iter.current->obj); - NMNDiscAddress * ndisc_addr; - guint32 lifetime; - guint32 preferred; - - if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address)) - continue; - - if (addr->n_ifa_flags & IFA_F_TENTATIVE || addr->n_ifa_flags & IFA_F_DADFAILED) - continue; - - if (addr->plen != 64) - continue; - - lifetime = nmp_utils_lifetime_get(addr->timestamp, - addr->lifetime, - addr->preferred, - NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000, - &preferred); - if (!lifetime) - continue; - - g_array_set_size(addresses, addresses->len + 1); - ndisc_addr = &g_array_index(addresses, NMNDiscAddress, addresses->len - 1); - ndisc_addr->address = addr->address; - ndisc_addr->expiry_msec = - _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, lifetime); - ndisc_addr->expiry_preferred_msec = - _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, preferred); - } - - len = nm_ip6_config_get_num_nameservers(priv->ip_config_6); - dns_servers = g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscDNSServer), len); - g_array_set_size(dns_servers, len); - for (i = 0; i < len; i++) { - const struct in6_addr *nameserver = nm_ip6_config_get_nameserver(priv->ip_config_6, i); - NMNDiscDNSServer * ndisc_nameserver; - - ndisc_nameserver = &g_array_index(dns_servers, NMNDiscDNSServer, i); - ndisc_nameserver->address = *nameserver; - ndisc_nameserver->expiry_msec = - _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME); - } - - len = nm_ip6_config_get_num_searches(priv->ip_config_6); - dns_domains = g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscDNSDomain), len); - g_array_set_size(dns_domains, len); - for (i = 0; i < len; i++) { - const char * search = nm_ip6_config_get_search(priv->ip_config_6, i); - NMNDiscDNSDomain *ndisc_search; - - ndisc_search = &g_array_index(dns_domains, NMNDiscDNSDomain, i); - ndisc_search->domain = (char *) search; - ndisc_search->expiry_msec = - _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME); - } - - nm_ndisc_set_config(ndisc, addresses, dns_servers, dns_domains); -} - -static void device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceInterfaceFlags flags = NM_DEVICE_INTERFACE_FLAG_NONE; if (plink && NM_FLAGS_HAS(plink->n_ifi_flags, IFF_UP)) @@ -5378,14 +6398,15 @@ device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink) } static gboolean -device_link_changed(NMDevice *self) +device_link_changed(gpointer user_data) { - NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self); - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - gboolean ip_ifname_changed = FALSE; + NMDevice *self = user_data; + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gboolean ip_ifname_changed = FALSE; nm_auto_nmpobj const NMPObject *pllink_keep_alive = NULL; - const NMPlatformLink * pllink; - const char * str; + const NMPlatformLink *pllink; + const char *str; int ifindex; gboolean was_up; gboolean update_unmanaged_specs = FALSE; @@ -5446,14 +6467,15 @@ device_link_changed(NMDevice *self) /* If the device has no explicit ip_iface, then changing iface changes ip_iface too. */ ip_ifname_changed = !priv->ip_iface; - if (nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT)) - nm_device_set_unmanaged_by_user_settings(self); - else + if (!nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT)) { + /* Since the interface name changed, we need to re-evaluate the + * user settings specs. */ update_unmanaged_specs = TRUE; + } _notify(self, PROP_IFACE); if (ip_ifname_changed) - _notify(self, PROP_IP_IFACE); + update_prop_ip_iface(self); /* Re-match available connections against the new interface name */ nm_device_recheck_available_connections(self); @@ -5464,8 +6486,8 @@ device_link_changed(NMDevice *self) nm_device_emit_recheck_auto_activate(self); } - if (priv->ndisc && pllink->inet6_token.id) { - if (nm_ndisc_set_iid(priv->ndisc, pllink->inet6_token)) + if (priv->ipac6_data.ndisc && pllink->inet6_token.id) { + if (nm_ndisc_set_iid(priv->ipac6_data.ndisc, pllink->inet6_token, TRUE)) _LOGD(LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface); } @@ -5508,31 +6530,35 @@ device_link_changed(NMDevice *self) } } + /* The assume check should happen before the device transitions to + * UNAVAILABLE, because in UNAVAILABLE we already clean up the IP + * configuration. Therefore, this function should never trigger a + * sync state transition. + */ nm_device_queue_recheck_assume(self); - nm_device_set_unmanaged_by_flags(self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); + nm_device_set_unmanaged_by_flags_queue(self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); } - set_unmanaged_external_down(self, FALSE); + _dev_unmanaged_check_external_down(self, FALSE, FALSE); device_recheck_slave_status(self, pllink); if (priv->up && (!was_up || seen_down)) { /* the link was down and just came up. That happens for example, while changing MTU. - * We must restore IP configuration. */ - if (NM_IN_SET(priv->ip_state_4, NM_DEVICE_IP_STATE_CONF, NM_DEVICE_IP_STATE_DONE)) { - if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) - _LOGW(LOGD_IP4, "failed applying IP4 config after link comes up again"); - } - - priv->linklocal6_dad_counter = 0; - if (NM_IN_SET(priv->ip_state_6, NM_DEVICE_IP_STATE_CONF, NM_DEVICE_IP_STATE_DONE)) { - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "failed applying IP6 config after link comes up again"); - } + * We must restore IP configuration. + * + * FIXME(l3cfg): when NML3Cfg notices that the device goes down and up, then + * it should automatically schedule a REAPPLY commit -- provided that the current + * commit-type is >= UPDATE. The idea is to move logic away from NMDevice + * so that it theoretically would also work for NMVpnConnection (although, + * NMVpnConnection should become like a regular device, akin to NMDevicePpp). + */ + if (!nm_device_sys_iface_state_is_external(self)) + nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE); } if (update_unmanaged_specs) - nm_device_set_unmanaged_by_user_settings(self); + nm_device_set_unmanaged_by_user_settings(self, FALSE); if (got_hw_addr && !priv->up && nm_device_get_state(self) == NM_DEVICE_STATE_UNAVAILABLE) { /* @@ -5550,11 +6576,12 @@ device_link_changed(NMDevice *self) } static gboolean -device_ip_link_changed(NMDevice *self) +device_ip_link_changed(gpointer user_data) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevice *self = user_data; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const NMPlatformLink *pllink; - const char * ip_iface; + const char *ip_iface; priv->device_ip_link_changed_id = 0; @@ -5586,7 +6613,7 @@ device_ip_link_changed(NMDevice *self) ip_iface); g_free(priv->ip_iface_); priv->ip_iface_ = g_strdup(ip_iface); - _notify(self, PROP_IP_IFACE); + update_prop_ip_iface(self); nm_device_update_dynamic_ip_setup(self); } @@ -5595,15 +6622,15 @@ device_ip_link_changed(NMDevice *self) } static void -link_changed_cb(NMPlatform * platform, +link_changed_cb(NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink *info, int change_type_i, - NMDevice * self) + NMDevice *self) { const NMPlatformSignalChangeType change_type = change_type_i; - NMDevicePrivate * priv; + NMDevicePrivate *priv; if (change_type != NM_PLATFORM_SIGNAL_CHANGED) return; @@ -5614,13 +6641,12 @@ link_changed_cb(NMPlatform * platform, if (!(info->n_ifi_flags & IFF_UP)) priv->device_link_changed_down = TRUE; if (!priv->device_link_changed_id) { - priv->device_link_changed_id = g_idle_add((GSourceFunc) device_link_changed, self); + priv->device_link_changed_id = g_idle_add(device_link_changed, self); _LOGD(LOGD_DEVICE, "queued link change for ifindex %d", ifindex); } } else if (ifindex == nm_device_get_ip_ifindex(self)) { if (!priv->device_ip_link_changed_id) { - priv->device_ip_link_changed_id = - g_idle_add((GSourceFunc) device_ip_link_changed, self); + priv->device_ip_link_changed_id = g_idle_add(device_ip_link_changed, self); _LOGD(LOGD_DEVICE, "queued link change for ip-ifindex %d", ifindex); } } @@ -5703,14 +6729,14 @@ link_type_compatible(NMDevice *self, NMLinkType link_type, gboolean *out_compati * Returns: %TRUE on success, %FALSE on error */ gboolean -nm_device_realize_start(NMDevice * self, +nm_device_realize_start(NMDevice *self, const NMPlatformLink *plink, gboolean assume_state_guess_assume, - const char * assume_state_connection_uuid, + const char *assume_state_connection_uuid, gboolean set_nm_owned, NMUnmanFlagOp unmanaged_user_explicit, - gboolean * out_compatible, - GError ** error) + gboolean *out_compatible, + GError **error) { nm_auto_nmpobj const NMPObject *plink_keep_alive = NULL; @@ -5757,14 +6783,14 @@ nm_device_realize_start(NMDevice * self, * Returns: %TRUE on success, %FALSE on error */ gboolean -nm_device_create_and_realize(NMDevice * self, +nm_device_create_and_realize(NMDevice *self, NMConnection *connection, - NMDevice * parent, - GError ** error) + NMDevice *parent, + GError **error) { nm_auto_nmpobj const NMPObject *plink_keep_alive = NULL; - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - const NMPlatformLink * plink; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const NMPlatformLink *plink; gboolean nm_owned; /* Must be set before device is realized */ @@ -5812,7 +6838,7 @@ void nm_device_update_from_platform_link(NMDevice *self, const NMPlatformLink *plink) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const char * str; + const char *str; gboolean ifindex_changed; guint32 mtu; @@ -5889,9 +6915,9 @@ sriov_op_start(NMDevice *self, SriovOp *op) static void sriov_op_cb(GError *error, gpointer user_data) { - SriovOp * op = user_data; + SriovOp *op = user_data; gs_unref_object NMDevice *self = op->device; - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); nm_assert(op == priv->sriov.pending); @@ -5941,7 +6967,7 @@ sriov_op_queue_op(NMDevice *self, SriovOp *op) } static void -sriov_op_queue(NMDevice * self, +sriov_op_queue(NMDevice *self, guint num_vfs, NMOptionBool autoprobe, NMPlatformAsyncCallback callback, @@ -6000,11 +7026,11 @@ device_init_static_sriov_num_vfs(NMDevice *self) } static void -config_changed(NMConfig * config, - NMConfigData * config_data, +config_changed(NMConfig *config, + NMConfigData *config_data, NMConfigChangeFlags changes, - NMConfigData * old_data, - NMDevice * self) + NMConfigData *old_data, + NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -6043,19 +7069,19 @@ realize_start_notify(NMDevice *self, const NMPlatformLink *pllink) * stuff). */ static void -realize_start_setup(NMDevice * self, +realize_start_setup(NMDevice *self, const NMPlatformLink *plink, gboolean assume_state_guess_assume, - const char * assume_state_connection_uuid, + const char *assume_state_connection_uuid, gboolean set_nm_owned, NMUnmanFlagOp unmanaged_user_explicit, gboolean force_platform_init) { - NMDevicePrivate * priv; - NMDeviceClass * klass; - NMPlatform * platform; + NMDevicePrivate *priv; + NMDeviceClass *klass; + NMPlatform *platform; NMDeviceCapabilities capabilities = 0; - NMConfig * config; + NMConfig *config; guint refresh_rate_ms; gboolean unmanaged; @@ -6072,8 +7098,6 @@ realize_start_setup(NMDevice * self, g_return_if_fail(nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT)); g_return_if_fail(priv->ip_ifindex <= 0); g_return_if_fail(priv->ip_iface == NULL); - g_return_if_fail(!priv->queued_ip_config_id_4); - g_return_if_fail(!priv->queued_ip_config_id_6); _LOGD(LOGD_DEVICE, "start setup of %s, kernel ifindex %d", @@ -6120,9 +7144,6 @@ realize_start_setup(NMDevice * self, if (priv->firmware_version) _notify(self, PROP_FIRMWARE_VERSION); - priv->ipv6ll_handle = (nm_platform_link_get_inet6_addr_gen_mode(platform, priv->ifindex) - == NM_IN6_ADDR_GEN_MODE_NONE); - if (nm_platform_link_supports_sriov(platform, priv->ifindex)) capabilities |= NM_DEVICE_CAP_SRIOV; } @@ -6180,7 +7201,7 @@ realize_start_setup(NMDevice * self, * or have IP addressing */ nm_device_set_unmanaged_flags(self, NM_UNMANAGED_EXTERNAL_DOWN, - is_unmanaged_external_down(self, TRUE)); + _dev_unmanaged_is_external_down(self, TRUE)); /* Unmanaged the loopback device with an explicit NM_UNMANAGED_BY_TYPE flag. * Later we might want to manage 'lo' too. Currently, that doesn't work because @@ -6219,9 +7240,6 @@ nm_device_realize_finish(NMDevice *self, const NMPlatformLink *plink) if (plink) device_recheck_slave_status(self, plink); - priv->update_ip_config_completed_v4 = FALSE; - priv->update_ip_config_completed_v6 = FALSE; - priv->real = TRUE; _notify(self, PROP_REAL); @@ -6242,7 +7260,7 @@ unrealize_notify(NMDevice *self) static gboolean available_connections_check_delete_unrealized_on_idle(gpointer user_data) { - NMDevice * self = user_data; + NMDevice *self = user_data; NMDevicePrivate *priv; g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE); @@ -6317,9 +7335,6 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) } } - nm_clear_g_source(&priv->queued_ip_config_id_4); - nm_clear_g_source(&priv->queued_ip_config_id_6); - g_object_freeze_notify(G_OBJECT(self)); NM_DEVICE_GET_CLASS(self)->unrealize_notify(self); @@ -6328,7 +7343,7 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) _set_ifindex(self, 0, FALSE); _set_ifindex(self, 0, TRUE); if (nm_clear_g_free(&priv->ip_iface_)) - _notify(self, PROP_IP_IFACE); + update_prop_ip_iface(self); priv->master_ifindex = 0; @@ -6444,7 +7459,7 @@ NMConnection * nm_device_new_default_connection(NMDevice *self) { NMConnection *connection; - GError * error = NULL; + GError *error = NULL; if (!NM_DEVICE_GET_CLASS(self)->new_default_connection) return NULL; @@ -6463,11 +7478,11 @@ nm_device_new_default_connection(NMDevice *self) } static void -slave_state_changed(NMDevice * slave, +slave_state_changed(NMDevice *slave, NMDeviceState slave_new_state, NMDeviceState slave_old_state, NMDeviceStateReason reason, - NMDevice * self) + NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean release = FALSE; @@ -6524,7 +7539,7 @@ nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure) { NMDevicePrivate *priv; NMDevicePrivate *slave_priv; - SlaveInfo * info; + SlaveInfo *info; gboolean changed = FALSE; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); @@ -6594,9 +7609,9 @@ void nm_device_master_check_slave_physical_port(NMDevice *self, NMDevice *slave, NMLogDomain log_domain) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const char * slave_physical_port_id, *existing_physical_port_id; - SlaveInfo * info; - CList * iter; + const char *slave_physical_port_id, *existing_physical_port_id; + SlaveInfo *info; + CList *iter; slave_physical_port_id = nm_device_get_physical_port_id(slave); if (!slave_physical_port_id) @@ -6627,9 +7642,9 @@ nm_device_master_check_slave_physical_port(NMDevice *self, NMDevice *slave, NMLo void nm_device_master_release_slaves(NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceStateReason reason; - CList * iter, *safe; + CList *iter, *safe; /* Don't release the slaves if this connection doesn't belong to NM. */ if (nm_device_sys_iface_state_is_external(self)) @@ -6683,117 +7698,6 @@ nm_device_get_master(NMDevice *self) return NULL; } -static gboolean -get_ip_config_may_fail(NMDevice *self, int addr_family) -{ - NMConnection * connection; - NMSettingIPConfig *s_ip; - - connection = nm_device_get_applied_connection(self); - - s_ip = nm_connection_get_setting_ip_config(connection, addr_family); - - return !s_ip || nm_setting_ip_config_get_may_fail(s_ip); -} - -/* - * check_ip_state - * - * When @full_state_update is TRUE, transition the device from IP_CONFIG to the - * next state according to the outcome of IPv4 and IPv6 configuration. @may_fail - * indicates that we are called just after the initial configuration and thus - * IPv4/IPv6 are allowed to fail if the ipvx.may-fail properties say so, because - * the IP methods couldn't even be started. - * If @full_state_update is FALSE, just check if the connection should be failed - * due to the state of both ip families and the ipvx.may-fail settings. - */ -static void -check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - gboolean ip4_disabled = FALSE, ip6_disabled = FALSE; - NMSettingIPConfig *s_ip4, *s_ip6; - NMDeviceState state; - int IS_IPv4; - - if (full_state_update && nm_device_get_state(self) != NM_DEVICE_STATE_IP_CONFIG) - return; - - /* Don't progress into IP_CHECK or SECONDARIES if we're waiting for the - * master to enslave us. */ - if (nm_active_connection_get_master(NM_ACTIVE_CONNECTION(priv->act_request.obj)) - && !priv->is_enslaved) - return; - - s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG); - if (s_ip4 - && nm_streq0(nm_setting_ip_config_get_method(s_ip4), NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) - ip4_disabled = TRUE; - - s_ip6 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG); - if (s_ip6 - && NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip6), - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) - ip6_disabled = TRUE; - - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE - && priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) { - /* Both method completed (or disabled), proceed with activation */ - nm_device_state_changed(self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); - return; - } - - for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { - if (priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_CONF - && priv->ip_req_timeout_source_x[IS_IPv4]) { - return; - } - } - - if ((priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL - || (ip4_disabled && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE)) - && (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL - || (ip6_disabled && priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE))) { - /* Either both methods failed, or only one failed and the other is - * disabled */ - if (nm_device_sys_iface_state_is_external_or_assume(self)) { - /* We have assumed configuration, but couldn't redo it. No problem, - * move to check state. */ - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE); - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE); - state = NM_DEVICE_STATE_IP_CHECK; - } else if (may_fail && get_ip_config_may_fail(self, AF_INET) - && get_ip_config_may_fail(self, AF_INET6)) { - /* Couldn't start either IPv6 and IPv4 autoconfiguration, - * but both are allowed to fail. */ - state = NM_DEVICE_STATE_SECONDARIES; - } else { - /* Autoconfiguration attempted without success. */ - state = NM_DEVICE_STATE_FAILED; - } - - if (full_state_update || state == NM_DEVICE_STATE_FAILED) { - nm_device_state_changed(self, state, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - return; - } - - /* If a method is still pending but required, wait */ - if (priv->ip_state_4 != NM_DEVICE_IP_STATE_DONE && !get_ip_config_may_fail(self, AF_INET)) - return; - if (priv->ip_state_6 != NM_DEVICE_IP_STATE_DONE && !get_ip_config_may_fail(self, AF_INET6)) - return; - - /* If at least a method has completed, proceed with activation */ - if ((priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !ip4_disabled) - || (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE && !ip6_disabled)) { - if (full_state_update) - nm_device_state_changed(self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); - return; - } -} - /** * nm_device_slave_notify_enslave: * @self: the slave device @@ -6806,7 +7710,7 @@ static void nm_device_slave_notify_enslave(NMDevice *self, gboolean success) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection = nm_device_get_applied_connection(self); + NMConnection *connection = nm_device_get_applied_connection(self); gboolean activating = (priv->state == NM_DEVICE_STATE_IP_CONFIG); g_return_if_fail(priv->master); @@ -6833,13 +7737,17 @@ nm_device_slave_notify_enslave(NMDevice *self, gboolean success) } } - if (activating) { - if (success) - check_ip_state(self, FALSE, TRUE); - else - nm_device_queue_state(self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); - } else + if (!activating) { nm_device_queue_recheck_assume(self); + return; + } + + if (!success) { + nm_device_queue_state(self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN); + return; + } + + nm_device_activate_schedule_stage3_ip_config(self, FALSE); } /** @@ -6853,8 +7761,8 @@ static void nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection = nm_device_get_applied_connection(self); - const char * master_status; + NMConnection *connection = nm_device_get_applied_connection(self); + const char *master_status; g_return_if_fail(priv->master); @@ -6913,6 +7821,9 @@ nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config) g_return_if_fail(NM_IS_DEVICE(self)); + _dev_ipdhcpx_cleanup(self, AF_INET, TRUE, FALSE); + _dev_ipdhcpx_cleanup(self, AF_INET6, TRUE, FALSE); + priv = NM_DEVICE_GET_PRIVATE(self); if (priv->master) { /* this is called when something externally messes with the slave or during shut-down. @@ -6924,15 +7835,7 @@ nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config) NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } - if (unconfigure_ip_config) { - nm_device_set_ip_config(self, AF_INET, NULL, FALSE, NULL); - nm_device_set_ip_config(self, AF_INET6, NULL, FALSE, NULL); - } else { - if (priv->dhcp_data_4.client) - nm_dhcp_client_stop(priv->dhcp_data_4.client, FALSE); - if (priv->dhcp_data_6.client) - nm_dhcp_client_stop(priv->dhcp_data_6.client, FALSE); - } + _dev_l3_register_l3cds(self, priv->l3cfg, FALSE, unconfigure_ip_config); } static gboolean @@ -7033,7 +7936,7 @@ nm_device_autoconnect_blocked_get(NMDevice *self, NMDeviceAutoconnectBlockedFlag } void -nm_device_autoconnect_blocked_set_full(NMDevice * self, +nm_device_autoconnect_blocked_set_full(NMDevice *self, NMDeviceAutoconnectBlockedFlags mask, NMDeviceAutoconnectBlockedFlags value) { @@ -7068,8 +7971,8 @@ nm_device_autoconnect_blocked_set_full(NMDevice * self, static gboolean autoconnect_allowed_accumulator(GSignalInvocationHint *ihint, - GValue * return_accu, - const GValue * handler_return, + GValue *return_accu, + const GValue *handler_return, gpointer data) { if (!g_value_get_boolean(handler_return)) @@ -7089,7 +7992,7 @@ gboolean nm_device_autoconnect_allowed(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); GValue instance = G_VALUE_INIT; GValue retval = G_VALUE_INIT; @@ -7190,22 +8093,36 @@ nm_device_can_auto_connect(NMDevice *self, NMSettingsConnection *sett_conn, char static gboolean device_has_config(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const NMDedupMultiHeadEntry *head_entry; + const NMPlatformLink *pllink; + NMPLookup lookup; + + pllink = nm_l3cfg_get_pllink(priv->l3cfg, TRUE); + if (!pllink) + return FALSE; - /* Check for IP configuration. */ - if (priv->ip_config_4 && nm_ip4_config_get_num_addresses(priv->ip_config_4)) + if (pllink->master > 0) { + /* Master-slave relationship is also a configuration */ return TRUE; - if (priv->ip_config_6 && nm_ip6_config_get_num_addresses(priv->ip_config_6)) + } + + head_entry = nm_platform_lookup( + nm_device_get_platform(self), + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, pllink->ifindex)); + if (head_entry) return TRUE; - /* The existence of a software device is good enough. */ - if (nm_device_is_software(self) && nm_device_is_real(self)) + head_entry = nm_platform_lookup( + nm_device_get_platform(self), + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, pllink->ifindex)); + if (head_entry) return TRUE; - /* Master-slave relationship is also a configuration */ - if (!c_list_is_empty(&priv->slaves) - || nm_platform_link_get_master(nm_device_get_platform(self), priv->ifindex) > 0) + if (nm_device_is_software(self) && nm_device_is_real(self)) { + /* The existence of a software device is good enough. */ return TRUE; + } return FALSE; } @@ -7224,10 +8141,10 @@ device_has_config(NMDevice *self) * %FALSE on failure. */ gboolean -nm_device_master_update_slave_connection(NMDevice * self, - NMDevice * slave, +nm_device_master_update_slave_connection(NMDevice *self, + NMDevice *slave, NMConnection *connection, - GError ** error) + GError **error) { NMDeviceClass *klass; gboolean success; @@ -7293,19 +8210,19 @@ NMConnection * nm_device_generate_connection(NMDevice *self, NMDevice *master, gboolean *out_maybe_later, - GError ** error) + GError **error) { - NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const char * ifname = nm_device_get_iface(self); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const char *ifname = nm_device_get_iface(self); gs_unref_object NMConnection *connection = NULL; - NMSetting * s_con; - NMSetting * s_ip4; - NMSetting * s_ip6; + NMSetting *s_con; + NMSetting *s_ip4; + NMSetting *s_ip6; char uuid[37]; - const char * ip4_method, *ip6_method; - GError * local = NULL; - const NMPlatformLink * pllink; + const char *ip4_method, *ip6_method; + GError *local = NULL; + const NMPlatformLink *pllink; NM_SET_OUT(out_maybe_later, FALSE); @@ -7363,10 +8280,16 @@ nm_device_generate_connection(NMDevice *self, } } else { /* Only regular and master devices get IP configuration; slaves do not */ - s_ip4 = nm_ip4_config_create_setting(priv->ip_config_4); + s_ip4 = nm_utils_platform_capture_ip_setting(nm_device_get_platform(self), + AF_INET, + nm_device_get_ip_ifindex(self), + FALSE); nm_connection_add_setting(connection, s_ip4); - s_ip6 = nm_ip6_config_create_setting(priv->ip_config_6, _get_maybe_ipv6_disabled(self)); + s_ip6 = nm_utils_platform_capture_ip_setting(nm_device_get_platform(self), + AF_INET6, + nm_device_get_ip_ifindex(self), + _get_maybe_ipv6_disabled(self)); nm_connection_add_setting(connection, s_ip6); nm_connection_add_setting(connection, nm_setting_proxy_new()); @@ -7449,11 +8372,11 @@ nm_device_generate_connection(NMDevice *self, * Returns: success or failure. */ gboolean -nm_device_complete_connection(NMDevice * self, - NMConnection * connection, - const char * specific_object, +nm_device_complete_connection(NMDevice *self, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMDeviceClass *klass; @@ -7511,14 +8434,14 @@ nm_device_match_parent(NMDevice *self, const char *parent) } gboolean -nm_device_match_parent_hwaddr(NMDevice * device, +nm_device_match_parent_hwaddr(NMDevice *device, NMConnection *connection, gboolean fail_if_no_hwaddr) { NMSettingWired *s_wired; - NMDevice * parent_device; - const char * setting_mac; - const char * parent_mac; + NMDevice *parent_device; + const char *setting_mac; + const char *parent_mac; s_wired = nm_connection_get_setting_wired(connection); if (!s_wired) @@ -7539,13 +8462,13 @@ nm_device_match_parent_hwaddr(NMDevice * device, static gboolean check_connection_compatible(NMDevice *self, NMConnection *connection, GError **error) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const char * device_iface = nm_device_get_iface(self); - gs_free_error GError *local = NULL; - gs_free char * conn_iface = NULL; - NMDeviceClass * klass; - NMSettingMatch * s_match; - const GSList * specs; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const char *device_iface = nm_device_get_iface(self); + gs_free_error GError *local = NULL; + gs_free char *conn_iface = NULL; + NMDeviceClass *klass; + NMSettingMatch *s_match; + const GSList *specs; gboolean has_match = FALSE; klass = NM_DEVICE_GET_CLASS(self); @@ -7668,7 +8591,7 @@ gboolean nm_device_check_slave_connection_compatible(NMDevice *self, NMConnection *slave) { NMSettingConnection *s_con; - const char * connection_type, *slave_type; + const char *connection_type, *slave_type; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); g_return_val_if_fail(NM_IS_CONNECTION(slave), FALSE); @@ -7746,7 +8669,7 @@ nm_device_unmanage_on_quit(NMDevice *self) static gboolean nm_device_emit_recheck_assume(gpointer user_data) { - NMDevice * self = user_data; + NMDevice *self = user_data; NMDevicePrivate *priv; g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE); @@ -7772,7 +8695,7 @@ nm_device_queue_recheck_assume(NMDevice *self) static gboolean recheck_available(gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); + NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean now_available; NMDeviceState state = nm_device_get_state(self); @@ -7810,7 +8733,7 @@ recheck_available(gpointer user_data) } void -nm_device_queue_recheck_available(NMDevice * self, +nm_device_queue_recheck_available(NMDevice *self, NMDeviceStateReason available_reason, NMDeviceStateReason unavailable_reason) { @@ -7832,27 +8755,13 @@ nm_device_emit_recheck_auto_activate(NMDevice *self) g_signal_emit(self, signals[RECHECK_AUTO_ACTIVATE], 0); } -static void -dnsmasq_state_changed_cb(NMDnsMasqManager *manager, guint32 status, gpointer user_data) -{ - NMDevice *self = NM_DEVICE(user_data); - - switch (status) { - case NM_DNSMASQ_STATUS_DEAD: - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - break; - default: - break; - } -} - void -nm_device_auth_request(NMDevice * self, - GDBusMethodInvocation * context, - NMConnection * connection, - const char * permission, +nm_device_auth_request(NMDevice *self, + GDBusMethodInvocation *context, + NMConnection *connection, + const char *permission, gboolean allow_interaction, - GCancellable * cancellable, + GCancellable *cancellable, NMManagerDeviceAuthRequestFunc callback, gpointer user_data) { @@ -7870,156 +8779,120 @@ nm_device_auth_request(NMDevice * self, /*****************************************************************************/ static void -activation_source_clear(NMDevice *self, int addr_family) +activation_source_clear(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->activation_source_id_x[IS_IPv4] != 0) { + if (nm_clear_g_source_inst(&priv->activation_idle_source)) { _LOGD(LOGD_DEVICE, - "activation-stage: clear %s,v%c (id %u)", - _activation_func_to_string(priv->activation_source_func_x[IS_IPv4]), - nm_utils_addr_family_to_char(addr_family), - priv->activation_source_id_x[IS_IPv4]); - nm_clear_g_source(&priv->activation_source_id_x[IS_IPv4]); - priv->activation_source_func_x[IS_IPv4] = NULL; + "activation-stage: clear %s", + _activation_func_to_string(priv->activation_func)); + priv->activation_func = NULL; } } static gboolean -activation_source_handle_cb(NMDevice *self, int addr_family) +activation_source_handle_cb(gpointer user_data) { - NMDevicePrivate * priv; - const int IS_IPv4 = NM_IS_IPv4(addr_family); - ActivationHandleFunc activation_source_func; - guint activation_source_id; + NMDevice *self = user_data; + NMDevicePrivate *priv; + ActivationHandleFunc activation_func; g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE); priv = NM_DEVICE_GET_PRIVATE(self); - activation_source_func = priv->activation_source_func_x[IS_IPv4]; - activation_source_id = priv->activation_source_id_x[IS_IPv4]; - - g_return_val_if_fail(activation_source_id != 0, G_SOURCE_REMOVE); - nm_assert(activation_source_func); - - priv->activation_source_func_x[IS_IPv4] = NULL; - priv->activation_source_id_x[IS_IPv4] = 0; + g_return_val_if_fail(priv->activation_idle_source, G_SOURCE_REMOVE); - _LOGD(LOGD_DEVICE, - "activation-stage: invoke %s,v%c (id %u)", - _activation_func_to_string(activation_source_func), - nm_utils_addr_family_to_char(addr_family), - activation_source_id); + nm_assert(priv->activation_func); - activation_source_func(self); + activation_func = priv->activation_func; + priv->activation_func = NULL; - _LOGT(LOGD_DEVICE, - "activation-stage: complete %s,v%c (id %u)", - _activation_func_to_string(activation_source_func), - nm_utils_addr_family_to_char(addr_family), - activation_source_id); + nm_clear_g_source_inst(&priv->activation_idle_source); - return G_SOURCE_REMOVE; -} + _LOGD(LOGD_DEVICE, "activation-stage: invoke %s", _activation_func_to_string(activation_func)); -static gboolean -activation_source_handle_cb_4(gpointer user_data) -{ - return activation_source_handle_cb(user_data, AF_INET); -} + activation_func(self); -static gboolean -activation_source_handle_cb_6(gpointer user_data) -{ - return activation_source_handle_cb(user_data, AF_INET6); + return G_SOURCE_CONTINUE; } static void -activation_source_schedule(NMDevice *self, ActivationHandleFunc func, int addr_family) +activation_source_schedule(NMDevice *self, ActivationHandleFunc func) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); - guint new_id = 0; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->activation_source_id_x[IS_IPv4] != 0 - && priv->activation_source_func_x[IS_IPv4] == func) { + if (priv->activation_idle_source && priv->activation_func == func) { /* Scheduling the same stage multiple times is fine. */ _LOGT(LOGD_DEVICE, - "activation-stage: already scheduled %s,v%c (id %u)", - _activation_func_to_string(func), - nm_utils_addr_family_to_char(addr_family), - priv->activation_source_id_x[IS_IPv4]); + "activation-stage: already scheduled %s", + _activation_func_to_string(func)); return; } - new_id = - g_idle_add(IS_IPv4 ? activation_source_handle_cb_4 : activation_source_handle_cb_6, self); - - if (priv->activation_source_id_x[IS_IPv4] != 0) { + if (priv->activation_idle_source) { _LOGD(LOGD_DEVICE, - "activation-stage: schedule %s,v%c which replaces %s,v%c (id %u -> %u)", + "activation-stage: schedule %s (which replaces %s)", _activation_func_to_string(func), - nm_utils_addr_family_to_char(addr_family), - _activation_func_to_string(priv->activation_source_func_x[IS_IPv4]), - nm_utils_addr_family_to_char(addr_family), - priv->activation_source_id_x[IS_IPv4], - new_id); - nm_clear_g_source(&priv->activation_source_id_x[IS_IPv4]); + _activation_func_to_string(priv->activation_func)); + nm_clear_g_source_inst(&priv->activation_idle_source); } else { - _LOGD(LOGD_DEVICE, - "activation-stage: schedule %s,v%c (id %u)", - _activation_func_to_string(func), - nm_utils_addr_family_to_char(addr_family), - new_id); + _LOGD(LOGD_DEVICE, "activation-stage: schedule %s", _activation_func_to_string(func)); } - priv->activation_source_func_x[IS_IPv4] = func; - priv->activation_source_id_x[IS_IPv4] = new_id; + priv->activation_idle_source = nm_g_idle_add_source(activation_source_handle_cb, self); + priv->activation_func = func; } static void -activation_source_invoke_sync(NMDevice *self, ActivationHandleFunc func, int addr_family) +activation_source_invoke_sync(NMDevice *self, ActivationHandleFunc func) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->activation_source_id_x[IS_IPv4] == 0) { + if (!priv->activation_idle_source) { _LOGD(LOGD_DEVICE, - "activation-stage: synchronously invoke %s,v%c", - _activation_func_to_string(func), - nm_utils_addr_family_to_char(addr_family)); - } else if (priv->activation_source_func_x[IS_IPv4] == func) { + "activation-stage: synchronously invoke %s", + _activation_func_to_string(func)); + } else if (priv->activation_func == func) { _LOGD(LOGD_DEVICE, - "activation-stage: synchronously invoke %s,v%c which was already scheduled (id %u)", - _activation_func_to_string(func), - nm_utils_addr_family_to_char(addr_family), - priv->activation_source_id_x[IS_IPv4]); + "activation-stage: synchronously invoke %s (which was already scheduled)", + _activation_func_to_string(func)); } else { _LOGD(LOGD_DEVICE, - "activation-stage: synchronously invoke %s,v%c which replaces %s,v%c (id %u)", + "activation-stage: synchronously invoke %s (which replaces %s)", _activation_func_to_string(func), - nm_utils_addr_family_to_char(addr_family), - _activation_func_to_string(priv->activation_source_func_x[IS_IPv4]), - nm_utils_addr_family_to_char(addr_family), - priv->activation_source_id_x[IS_IPv4]); + _activation_func_to_string(priv->activation_func)); } - nm_clear_g_source(&priv->activation_source_id_x[IS_IPv4]); - priv->activation_source_func_x[IS_IPv4] = NULL; + nm_clear_g_source_inst(&priv->activation_idle_source); + priv->activation_func = NULL; func(self); } +static void +activation_source_invoke_or_schedule(NMDevice *self, ActivationHandleFunc func, gboolean do_sync) +{ + nm_assert(NM_IS_DEVICE(self)); + nm_assert(NM_DEVICE_GET_PRIVATE(self)->act_request.obj); + nm_assert(func); + + if (do_sync) { + activation_source_invoke_sync(self, func); + return; + } + activation_source_schedule(self, func); +} + /*****************************************************************************/ static void master_ready(NMDevice *self, NMActiveConnection *active) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMActiveConnection *master_connection; - NMDevice * master; + NMDevice *master; /* Notify a master device that it has a new slave */ nm_assert(nm_active_connection_get_master_ready(active)); @@ -8057,10 +8930,10 @@ master_ready_cb(NMActiveConnection *active, GParamSpec *pspec, NMDevice *self) static NMPlatformVF * sriov_vf_config_to_platform(NMDevice *self, NMSriovVF *vf, GError **error) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gs_free NMPlatformVF *plat_vf = NULL; - const guint * vlan_ids; - GVariant * variant; + const guint *vlan_ids; + GVariant *variant; guint i, num_vlans; gsize length; @@ -8131,8 +9004,8 @@ sriov_vf_config_to_platform(NMDevice *self, NMSriovVF *vf, GError **error) static void sriov_params_cb(GError *error, gpointer user_data) { - NMDevice * self; - NMDevicePrivate *priv; + NMDevice *self; + NMDevicePrivate *priv; nm_auto_freev NMPlatformVF **plat_vfs = NULL; nm_utils_user_data_unpack(user_data, &self, &plat_vfs); @@ -8174,20 +9047,26 @@ sriov_params_cb(GError *error, gpointer user_data) static void activate_stage1_device_prepare(NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; NMActiveConnection *active; NMActiveConnection *master; - NMDeviceClass * klass; + NMDeviceClass *klass; - priv->v4_route_table_initialized = FALSE; - priv->v6_route_table_initialized = FALSE; + nm_assert((priv->ip_data_4.state == NM_DEVICE_IP_STATE_NONE) + == (priv->ip_data_6.state == NM_DEVICE_IP_STATE_NONE)); - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_NONE); - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_NONE); + if (priv->ip_data_4.state == NM_DEVICE_IP_STATE_NONE) { + _dev_ip_state_set_state(self, AF_INET, NM_DEVICE_IP_STATE_PENDING, "stage1"); + _dev_ip_state_set_state(self, AF_INET6, NM_DEVICE_IP_STATE_PENDING, "stage1"); - /* Notify the new ActiveConnection along with the state change */ - nm_dbus_track_obj_path_set(&priv->act_request, priv->act_request.obj, TRUE); + /* Notify the new ActiveConnection along with the state change */ + nm_dbus_track_obj_path_set(&priv->act_request, priv->act_request.obj, TRUE); + + priv->v4_route_table_initialized = FALSE; + priv->v6_route_table_initialized = FALSE; + priv->l3config_merge_flags_has = FALSE; + } nm_device_state_changed(self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); @@ -8201,11 +9080,11 @@ activate_stage1_device_prepare(NMDevice *self) else if (priv->ifindex > 0 && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV) && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { nm_auto_freev NMPlatformVF **plat_vfs = NULL; - gs_free_error GError *error = NULL; - NMSriovVF * vf; - NMTernary autoprobe; - guint num; - guint i; + gs_free_error GError *error = NULL; + NMSriovVF *vf; + NMTernary autoprobe; + guint num; + guint i; autoprobe = nm_setting_sriov_get_autoprobe_drivers(s_sriov); if (autoprobe == NM_TERNARY_DEFAULT) { @@ -8248,6 +9127,7 @@ activate_stage1_device_prepare(NMDevice *self) priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_PENDING; return; } + priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_COMPLETED; } @@ -8323,15 +9203,7 @@ activate_stage1_device_prepare(NMDevice *self) void nm_device_activate_schedule_stage1_device_prepare(NMDevice *self, gboolean do_sync) { - g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(NM_DEVICE_GET_PRIVATE(self)->act_request.obj); - - if (!do_sync) { - activation_source_schedule(self, activate_stage1_device_prepare, AF_INET); - return; - } - - activation_source_invoke_sync(self, activate_stage1_device_prepare, AF_INET); + activation_source_invoke_or_schedule(self, activate_stage1_device_prepare, do_sync); } static NMActStageReturn @@ -8408,8 +9280,8 @@ static void _routing_rules_sync(NMDevice *self, NMTernary set_mode) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMPRulesManager *rules_manager = nm_netns_get_rules_manager(nm_device_get_netns(self)); - NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self); + NMPRouteManager *route_manager = nm_netns_get_route_manager(nm_device_get_netns(self)); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); gboolean untrack_only_dirty = FALSE; gboolean keep_deleted_rules; gpointer user_tag_1; @@ -8420,15 +9292,12 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) user_tag_2 = &priv->v6_route_table; if (set_mode == NM_TERNARY_TRUE) { - NMConnection * applied_connection; + NMConnection *applied_connection; NMSettingIPConfig *s_ip; guint i, num; int is_ipv4; untrack_only_dirty = TRUE; - nmp_rules_manager_set_dirty(rules_manager, user_tag_1); - if (klass->get_extra_rules) - nmp_rules_manager_set_dirty(rules_manager, user_tag_2); applied_connection = nm_device_get_applied_connection(self); @@ -8442,19 +9311,19 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) num = nm_setting_ip_config_get_num_routing_rules(s_ip); for (i = 0; i < num; i++) { NMPlatformRoutingRule plrule; - NMIPRoutingRule * rule; + NMIPRoutingRule *rule; rule = nm_setting_ip_config_get_routing_rule(s_ip, i); nm_ip_routing_rule_to_platform(rule, &plrule); /* We track this rule, but we also make it explicitly not weakly-tracked - * (meaning to untrack NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG at + * (meaning to untrack NMP_ROUTE_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG at * the same time). */ - nmp_rules_manager_track(rules_manager, - &plrule, - 10, - user_tag_1, - NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG); + nmp_route_manager_track_rule(route_manager, + &plrule, + 10, + user_tag_1, + NMP_ROUTE_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG); } } @@ -8464,24 +9333,25 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) extra_rules = klass->get_extra_rules(self); if (extra_rules) { for (i = 0; i < extra_rules->len; i++) { - nmp_rules_manager_track(rules_manager, - NMP_OBJECT_CAST_ROUTING_RULE(extra_rules->pdata[i]), - 10, - user_tag_2, - NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG); + nmp_route_manager_track_rule( + route_manager, + NMP_OBJECT_CAST_ROUTING_RULE(extra_rules->pdata[i]), + 10, + user_tag_2, + NMP_ROUTE_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG); } } } } - nmp_rules_manager_untrack_all(rules_manager, user_tag_1, !untrack_only_dirty); + nmp_route_manager_untrack_all(route_manager, user_tag_1, !untrack_only_dirty, TRUE); if (klass->get_extra_rules) - nmp_rules_manager_untrack_all(rules_manager, user_tag_2, !untrack_only_dirty); + nmp_route_manager_untrack_all(route_manager, user_tag_2, !untrack_only_dirty, TRUE); keep_deleted_rules = FALSE; if (set_mode == NM_TERNARY_DEFAULT) { /* when exiting NM, we leave the device up and the rules configured. - * We just all nmp_rules_manager_sync() to forget about the synced rules, + * We just call nmp_route_manager_sync() to forget about the synced rules, * but we don't actually delete them. * * FIXME: that is a problem after restart of NetworkManager, because these @@ -8495,7 +9365,7 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode) * file and track them after restart again. */ keep_deleted_rules = TRUE; } - nmp_rules_manager_sync(rules_manager, keep_deleted_rules); + nmp_route_manager_sync(route_manager, NMP_OBJECT_TYPE_ROUTING_RULE, keep_deleted_rules); } static gboolean @@ -8503,8 +9373,8 @@ tc_commit(NMDevice *self) { gs_unref_ptrarray GPtrArray *qdiscs = NULL; gs_unref_ptrarray GPtrArray *tfilters = NULL; - NMSettingTCConfig * s_tc; - NMPlatform * platform; + NMSettingTCConfig *s_tc; + NMPlatform *platform; int ip_ifindex; s_tc = nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG); @@ -8536,11 +9406,11 @@ static void activate_stage2_device_config(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMDeviceClass * klass; + NMDeviceClass *klass; NMActStageReturn ret; - NMSettingWired * s_wired; + NMSettingWired *s_wired; gboolean no_firmware = FALSE; - CList * iter; + CList *iter; NMTernary accept_all_mac_addresses; nm_device_state_changed(self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); @@ -8588,7 +9458,7 @@ activate_stage2_device_config(NMDevice *self) /* If we have slaves that aren't yet enslaved, do that now */ c_list_for_each (iter, &priv->slaves) { - SlaveInfo * info = c_list_entry(iter, SlaveInfo, lst_slave); + SlaveInfo *info = c_list_entry(iter, SlaveInfo, lst_slave); NMDeviceState slave_state = nm_device_get_state(info->slave); if (slave_state == NM_DEVICE_STATE_IP_CONFIG) @@ -8623,1086 +9493,809 @@ activate_stage2_device_config(NMDevice *self) lldp_setup(self, NM_TERNARY_DEFAULT); - _commit_mtu(self, NULL); + _commit_mtu(self); - nm_device_activate_schedule_stage3_ip_config_start(self); + nm_device_activate_schedule_stage3_ip_config(self, TRUE); } void nm_device_activate_schedule_stage2_device_config(NMDevice *self, gboolean do_sync) { - g_return_if_fail(NM_IS_DEVICE(self)); - - if (!do_sync) { - activation_source_schedule(self, activate_stage2_device_config, AF_INET); - return; - } - - activation_source_invoke_sync(self, activate_stage2_device_config, AF_INET); -} - -void -nm_device_ip_method_failed(NMDevice *self, int addr_family, NMDeviceStateReason reason) -{ - g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL); - - if (get_ip_config_may_fail(self, addr_family)) - check_ip_state(self, FALSE, (nm_device_get_state(self) == NM_DEVICE_STATE_IP_CONFIG)); - else - nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, reason); + activation_source_invoke_or_schedule(self, activate_stage2_device_config, do_sync); } /*****************************************************************************/ static void -acd_data_destroy(gpointer ptr) +_dev_ipllx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state) { - AcdData *data = ptr; - int i; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - for (i = 0; data->configs && data->configs[i]; i++) - g_object_unref(data->configs[i]); - g_free(data->configs); - g_slice_free(AcdData, data); + if (priv->ipll_data_x[IS_IPv4].state != state) { + _LOGD_ipll(addr_family, + "set state %s (was %s)", + nm_device_ip_state_to_string(state), + nm_device_ip_state_to_string(priv->ipll_data_x[IS_IPv4].state)); + priv->ipll_data_x[IS_IPv4].state = state; + } } static void -ipv4_manual_method_apply(NMDevice *self, NMIP4Config **configs, gboolean success) +_dev_ipllx_cleanup(NMDevice *self, int addr_family) { - NMConnection *connection; - const char * method; - - connection = nm_device_get_applied_connection(self); - nm_assert(connection); - method = nm_utils_get_ip_config_method(connection, AF_INET); - nm_assert(NM_IN_STRSET(method, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL, - NM_SETTING_IP4_CONFIG_METHOD_AUTO)); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - if (!success) { - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE); - return; - } + if (IS_IPv4) { + if (nm_clear_pointer(&priv->ipll_data_4.v4.ipv4ll, nm_l3_ipv4ll_unref)) + nm_clear_pointer(&priv->ipll_data_4.v4.ipv4ll_registation, + nm_l3_ipv4ll_register_remove); + else + nm_assert(!priv->ipll_data_4.v4.ipv4ll_registation); - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) - nm_device_activate_schedule_ip_config_result(self, AF_INET, NULL); - else { - if (NM_DEVICE_GET_PRIVATE(self)->ip_state_4 != NM_DEVICE_IP_STATE_DONE) - ip_config_merge_and_apply(self, AF_INET, TRUE); + nm_clear_g_source_inst(&priv->ipll_data_4.v4.timeout_source); + } else { + nm_clear_pointer(&priv->ipll_data_6.v6.ipv6ll, nm_l3_ipv6ll_destroy); + priv->ipll_data_6.v6.llstate = NM_L3_IPV6LL_STATE_NONE; + priv->ipll_data_6.v6.lladdr = nm_ip_addr_zero.addr6; + nm_clear_g_source_inst(&priv->ipll_data_6.v6.retry_source); } -} -static void -acd_manager_probe_terminated(NMAcdManager *acd_manager, gpointer user_data) -{ - AcdData * data = user_data; - NMDevice * self; - NMDevicePrivate * priv; - NMDedupMultiIter ipconf_iter; - const NMPlatformIP4Address *address; - gboolean result, success = TRUE; - int i; - - g_assert(data); - self = data->device; - priv = NM_DEVICE_GET_PRIVATE(self); + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_X(IS_IPv4), NULL, FALSE); - for (i = 0; data->configs && data->configs[i]; i++) { - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, data->configs[i], &address) { - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + _dev_ipllx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE); +} - result = nm_acd_manager_check_address(acd_manager, address->address); - success &= result; +/*****************************************************************************/ - _NMLOG(result ? LOGL_DEBUG : LOGL_WARN, - LOGD_DEVICE, - "IPv4 DAD result: address %s is %s", - _nm_utils_inet4_ntop(address->address, sbuf), - result ? "unique" : "duplicate"); - } +static void +_dev_ipll4_notify_event(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NML3IPv4LLState ipv4ll_state; + const NML3ConfigData *l3cd; + NMDeviceIPState state; + + nm_assert(NM_IS_L3_IPV4LL(priv->ipll_data_4.v4.ipv4ll)); + nm_assert(priv->ipll_data_4.state >= NM_DEVICE_IP_STATE_PENDING); + + ipv4ll_state = nm_l3_ipv4ll_get_state(priv->ipll_data_4.v4.ipv4ll); + + if (nm_l3_ipv4ll_state_is_good(ipv4ll_state)) { + l3cd = nm_l3_ipv4ll_get_l3cd(priv->ipll_data_4.v4.ipv4ll); + nm_assert(NM_IS_L3_CONFIG_DATA(l3cd)); + nm_assert(!nm_l3_ipv4ll_is_timed_out(priv->ipll_data_4.v4.ipv4ll)); + state = NM_DEVICE_IP_STATE_READY; + } else if (priv->ipll_data_4.v4.ipv4ll + && nm_l3_ipv4ll_is_timed_out(priv->ipll_data_4.v4.ipv4ll)) { + l3cd = NULL; + state = NM_DEVICE_IP_STATE_FAILED; + } else { + l3cd = NULL; + state = (priv->ipll_data_4.state == NM_DEVICE_IP_STATE_PENDING) ? NM_DEVICE_IP_STATE_PENDING + : NM_DEVICE_IP_STATE_FAILED; } - data->callback(self, data->configs, success); + _dev_ipllx_set_state(self, AF_INET, state); + + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_4, l3cd, FALSE); - priv->acd.dad_list = g_slist_remove(priv->acd.dad_list, acd_manager); - nm_acd_manager_free(acd_manager); + _dev_ip_state_check_async(self, AF_INET); } -/** - * ipv4_dad_start: - * @self: device instance - * @configs: NULL-terminated array of IPv4 configurations - * @cb: callback function - * - * Start IPv4 DAD on device @self, check addresses in @configs and call @cb - * when the procedure ends. @cb will be called in any case, even if DAD can't - * be started. @configs will be unreferenced after @cb has been called. - */ static void -ipv4_dad_start(NMDevice *self, NMIP4Config **configs, AcdCallback cb) +_dev_ipll4_start(NMDevice *self) { - static const NMAcdCallbacks acd_callbacks = { - .probe_terminated_callback = acd_manager_probe_terminated, - .user_data_destroy = acd_data_destroy, - }; - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMAcdManager * acd_manager; - const NMPlatformIP4Address *address; - NMDedupMultiIter ipconf_iter; - AcdData * data; - guint timeout; - gboolean addr_found; - int r; - const guint8 * hwaddr_arr; - size_t length; - guint i; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + guint32 timeout_msec; - g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(configs); - g_return_if_fail(cb); + if (priv->ipll_data_4.state >= NM_DEVICE_IP_STATE_PENDING) + return; - for (i = 0, addr_found = FALSE; configs[i]; i++) { - if (nm_ip4_config_get_num_addresses(configs[i]) > 0) { - addr_found = TRUE; - break; - } - } + _dev_ipllx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_PENDING); - timeout = _prop_get_ipv4_dad_timeout(self); - hwaddr_arr = nm_platform_link_get_address(nm_device_get_platform(self), - nm_device_get_ip_ifindex(self), - &length); + timeout_msec = _prop_get_ipv4_dad_timeout(self); + if (timeout_msec == 0) + timeout_msec = NM_ACD_TIMEOUT_RFC5227_MSEC; - if (!timeout || !hwaddr_arr || !addr_found || length != ETH_ALEN - || nm_device_sys_iface_state_is_external_or_assume(self)) { - /* DAD not needed, signal success */ - cb(self, configs, TRUE); + priv->ipll_data_4.v4.ipv4ll = nm_l3cfg_access_ipv4ll(priv->l3cfg); + priv->ipll_data_4.v4.ipv4ll_registation = + nm_l3_ipv4ll_register_new(priv->ipll_data_4.v4.ipv4ll, timeout_msec); +} - for (i = 0; configs[i]; i++) - g_object_unref(configs[i]); - g_free(configs); +/*****************************************************************************/ - return; - } +static const char * +_device_get_dhcp_anycast_address(NMDevice *self) +{ + NMDeviceClass *klass; + + nm_assert(NM_IS_DEVICE(self)); - data = g_slice_new0(AcdData); - data->configs = configs; - data->callback = cb; - data->device = self; + klass = NM_DEVICE_GET_CLASS(self); - acd_manager = nm_acd_manager_new(nm_device_get_ip_ifindex(self), - hwaddr_arr, - length, - &acd_callbacks, - data); - priv->acd.dad_list = g_slist_append(priv->acd.dad_list, acd_manager); + if (klass->get_dhcp_anycast_address) + return klass->get_dhcp_anycast_address(self); - for (i = 0; configs[i]; i++) { - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, configs[i], &address) - nm_acd_manager_add_address(acd_manager, address->address); - } + return NULL; +} - r = nm_acd_manager_start_probe(acd_manager, timeout); - if (r < 0) { - _LOGW(LOGD_DEVICE, "acd probe failed"); +/*****************************************************************************/ - /* DAD could not be started, signal success */ - cb(self, configs, TRUE); +static IPDevStateData * +_dev_ipdev_data(NMDevice *self, int addr_family) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - priv->acd.dad_list = g_slist_remove(priv->acd.dad_list, acd_manager); - nm_acd_manager_free(acd_manager); + switch (addr_family) { + case AF_INET: + return &priv->ipdev_data_4; + case AF_INET6: + return &priv->ipdev_data_6; + default: + nm_assert_not_reached(); + /* fall-through */ + case AF_UNSPEC: + return &priv->ipdev_data_unspec; } } -/*****************************************************************************/ -/* IPv4LL stuff */ - static void -ipv4ll_cleanup(NMDevice *self) +_dev_ipdev_cleanup(NMDevice *self, int addr_family) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + IPDevStateData *p; - if (priv->ipv4ll) { - sd_ipv4ll_set_callback(priv->ipv4ll, NULL, NULL); - sd_ipv4ll_stop(priv->ipv4ll); - priv->ipv4ll = sd_ipv4ll_unref(priv->ipv4ll); + p = _dev_ipdev_data(self, addr_family); + if (p->state != NM_DEVICE_IP_STATE_NONE) { + _LOGD_ipdev(addr_family, "reset state"); + p->state = NM_DEVICE_IP_STATE_NONE; + p->failed_reason = NM_DEVICE_STATE_REASON_NONE; } - nm_clear_g_source(&priv->ipv4ll_timeout); + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DEVIP(addr_family), NULL, FALSE); } -static NMIP4Config * -ipv4ll_get_ip4_config(NMDevice *self, guint32 lla) +NMDeviceIPState +nm_device_devip_get_state(NMDevice *self, int addr_family) { - NMIP4Config * config = NULL; - NMPlatformIP4Address address; - NMPlatformIP4Route route; + g_return_val_if_fail(NM_IS_DEVICE(self), NM_DEVICE_IP_STATE_NONE); - config = nm_device_ip4_config_new(self); - g_assert(config); + return _dev_ipdev_data(self, addr_family)->state; +} - memset(&address, 0, sizeof(address)); - nm_platform_ip4_address_set_addr(&address, lla, 16); - address.addr_source = NM_IP_CONFIG_SOURCE_IP4LL; - nm_ip4_config_add_address(config, &address); +void +nm_device_devip_set_state_full(NMDevice *self, + int addr_family, + NMDeviceIPState ip_state, + const NML3ConfigData *l3cd, + NMDeviceStateReason failed_reason) +{ + NMDevicePrivate *priv; + IPDevStateData *p; + + g_return_if_fail(NM_IS_DEVICE(self)); + + priv = NM_DEVICE_GET_PRIVATE(self); + + nm_assert_addr_family_or_unspec(addr_family); + nm_assert(NM_IN_SET(ip_state, + NM_DEVICE_IP_STATE_PENDING, + NM_DEVICE_IP_STATE_READY, + NM_DEVICE_IP_STATE_FAILED)); + nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd)); - /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */ - memset(&route, 0, sizeof(route)); - route.network = htonl(0xE0000000L); - route.plen = 4; - route.rt_source = NM_IP_CONFIG_SOURCE_IP4LL; - route.table_coerced = nm_platform_route_table_coerce(nm_device_get_route_table(self, AF_INET)); - route.metric = nm_device_get_route_metric(self, AF_INET); - nm_ip4_config_add_route(config, &route, NULL); + nm_assert((ip_state != NM_DEVICE_IP_STATE_FAILED) + == (failed_reason == NM_DEVICE_STATE_REASON_NONE)); + nm_assert((ip_state != NM_DEVICE_IP_STATE_FAILED) || !l3cd); - return config; + p = _dev_ipdev_data(self, addr_family); + + if (p->state == ip_state && p->failed_reason == failed_reason + && priv->l3cds[L3_CONFIG_DATA_TYPE_DEVIP(addr_family)].d == l3cd) + return; + + if (ip_state == NM_DEVICE_IP_STATE_FAILED) { + _LOGD_ipdev(addr_family, + "set state=failed (reason %s)", + nm_device_state_reason_to_string_a(failed_reason)); + } else { + _LOGD_ipdev(addr_family, + "set state=%s%s", + nm_device_ip_state_to_string(ip_state), + l3cd ? " (has extra IP configuration)" : ""); + } + p->state = ip_state; + p->failed_reason = failed_reason; + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DEVIP(addr_family), l3cd, FALSE); + _dev_ip_state_check_async(self, addr_family); } +/*****************************************************************************/ + static void -nm_device_handle_ipv4ll_event(sd_ipv4ll *ll, int event, void *data) +_dev_ipmanual_set_state(NMDevice *self, int addr_family, NMDeviceIPState state) { - NMDevice * self = data; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - struct in_addr address; - NMIP4Config * config; - int r; + int IS_IPv4; - if (priv->act_request.obj == NULL) + if (addr_family == AF_UNSPEC) { + _dev_ipmanual_set_state(self, AF_INET, state); + _dev_ipmanual_set_state(self, AF_INET6, state); return; + } - nm_assert(nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET), - NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)); + IS_IPv4 = NM_IS_IPv4(addr_family); + if (priv->ipmanual_data.state_x[IS_IPv4] != state) { + _LOGD_ipmanual(addr_family, "set state %s", nm_device_ip_state_to_string(state)); + priv->ipmanual_data.state_x[IS_IPv4] = state; + } +} - switch (event) { - case SD_IPV4LL_EVENT_BIND: - r = sd_ipv4ll_get_address(ll, &address); - if (r < 0) { - _LOGE(LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED); - return; - } +static void +_dev_ipmanual_cleanup(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (!nm_utils_ip4_address_is_link_local(address.s_addr)) { - _LOGE(LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); - return; - } + if (priv->ipmanual_data.state_4 == NM_DEVICE_IP_STATE_NONE + && priv->ipmanual_data.state_6 == NM_DEVICE_IP_STATE_NONE) { + nm_assert(!priv->l3cds[L3_CONFIG_DATA_TYPE_MANUALIP].d); + return; + } - config = ipv4ll_get_ip4_config(self, address.s_addr); - if (config == NULL) { - _LOGE(LOGD_AUTOIP4, "failed to get IPv4LL config"); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); - return; - } + _dev_ipmanual_set_state(self, AF_UNSPEC, NM_DEVICE_IP_STATE_NONE); + nm_clear_g_source_inst(&priv->ipmanual_data.carrier_timeout); + priv->ipmanual_data.carrier_timeout_expired = FALSE; - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) { - nm_clear_g_source(&priv->ipv4ll_timeout); - nm_device_activate_schedule_ip_config_result(self, AF_INET, NM_IP_CONFIG_CAST(config)); - } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) { - applied_config_init(&priv->dev_ip_config_4, config); - if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) { - _LOGE(LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); - } - } else - g_assert_not_reached(); + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_MANUALIP, NULL, FALSE); - g_object_unref(config); - break; - default: - _LOGW(LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); - } + _dev_ip_state_check_async(self, AF_INET); + _dev_ip_state_check_async(self, AF_INET6); } static gboolean -ipv4ll_timeout_cb(gpointer user_data) +_dev_ipmanual_carrier_timeout(NMDevice *self) { - NMDevice * self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->ipv4ll_timeout) { - _LOGI(LOGD_AUTOIP4, "IPv4LL configuration timed out."); - priv->ipv4ll_timeout = 0; - ipv4ll_cleanup(self); - - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) - nm_device_activate_schedule_ip_config_timeout(self, AF_INET); - } + priv->ipmanual_data.carrier_timeout_expired = TRUE; + nm_clear_g_source_inst(&priv->ipmanual_data.carrier_timeout); + _dev_ipmanual_check_ready(self); - return FALSE; + return G_SOURCE_CONTINUE; } -static NMActStageReturn -ipv4ll_start(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - const struct ether_addr *addr; - int ifindex, r; - size_t addr_len; +static void +_dev_ipmanual_check_ready(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const NMPlatformLink *plink; + gboolean has_carrier; + NML3CfgCheckReadyFlags flags; + gboolean ready; + gboolean acd_used = FALSE; + int IS_IPv4; + + if (priv->ipmanual_data.state_4 != NM_DEVICE_IP_STATE_PENDING + && priv->ipmanual_data.state_6 != NM_DEVICE_IP_STATE_PENDING) { + /* we only care about PENDING to get it READY. Currently not other + * conditions are implemented. That is, we cannot get to FAILED + * (maybe we should, if DAD fails) and we cannot get from anything + * once we are READY. */ + return; + } - ipv4ll_cleanup(self); + plink = nm_l3cfg_get_pllink(priv->l3cfg, TRUE); + has_carrier = plink && NM_FLAGS_HAS(plink->n_ifi_flags, IFF_LOWER_UP); - r = sd_ipv4ll_new(&priv->ipv4ll); - if (r < 0) { - _LOGE(LOGD_AUTOIP4, "IPv4LL: new() failed with error %d", r); - return NM_ACT_STAGE_RETURN_FAILURE; + if (has_carrier) { + nm_clear_g_source_inst(&priv->ipmanual_data.carrier_timeout); + } else { + if (priv->ipmanual_data.carrier_timeout_expired) { + /* go on */ + } else if (priv->ipmanual_data.carrier_timeout) { + /* wait a bit more until timer expires */ + return; + } else { + priv->ipmanual_data.carrier_timeout = + nm_g_timeout_add_source(2000, G_SOURCE_FUNC(_dev_ipmanual_carrier_timeout), self); + return; + } } - r = sd_ipv4ll_attach_event(priv->ipv4ll, NULL, 0); - if (r < 0) { - _LOGE(LOGD_AUTOIP4, "IPv4LL: attach_event() failed with error %d", r); - return NM_ACT_STAGE_RETURN_FAILURE; + flags = NM_L3CFG_CHECK_READY_FLAGS_NONE; + if (has_carrier) { + flags |= NM_L3CFG_CHECK_READY_FLAGS_IP4_ACD_READY; + flags |= NM_L3CFG_CHECK_READY_FLAGS_IP6_DAD_READY; } - ifindex = nm_device_get_ip_ifindex(self); - addr = nm_platform_link_get_address(nm_device_get_platform(self), ifindex, &addr_len); - if (!addr || addr_len != ETH_ALEN) { - _LOGE(LOGD_AUTOIP4, "IPv4LL: can't retrieve hardware address"); - return NM_ACT_STAGE_RETURN_FAILURE; - } + for (IS_IPv4 = 0; IS_IPv4 < 2; IS_IPv4++) { + const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; - r = sd_ipv4ll_set_mac(priv->ipv4ll, addr); - if (r < 0) { - _LOGE(LOGD_AUTOIP4, "IPv4LL: set_mac() failed with error %d", r); - return NM_ACT_STAGE_RETURN_FAILURE; + ready = nm_l3cfg_check_ready(priv->l3cfg, + priv->l3cds[L3_CONFIG_DATA_TYPE_MANUALIP].d, + addr_family, + flags, + &acd_used); + if (acd_used) { + _dev_ipmanual_set_state(self, addr_family, NM_DEVICE_IP_STATE_FAILED); + _dev_ip_state_check_async(self, AF_UNSPEC); + } else if (ready) { + _dev_ipmanual_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY); + _dev_ip_state_check_async(self, AF_UNSPEC); + } } +} - r = sd_ipv4ll_set_ifindex(priv->ipv4ll, ifindex); - if (r < 0) { - _LOGE(LOGD_AUTOIP4, "IPv4LL: set_ifindex() failed with error %d", r); - return NM_ACT_STAGE_RETURN_FAILURE; - } +static void +_dev_ipmanual_start(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; + + if (priv->ipmanual_data.state_4 != NM_DEVICE_IP_STATE_NONE + || priv->ipmanual_data.state_6 != NM_DEVICE_IP_STATE_NONE) + return; - r = sd_ipv4ll_set_callback(priv->ipv4ll, nm_device_handle_ipv4ll_event, self); - if (r < 0) { - _LOGE(LOGD_AUTOIP4, "IPv4LL: set_callback() failed with error %d", r); - return NM_ACT_STAGE_RETURN_FAILURE; + if (nm_device_get_ip_ifindex(self) > 0) { + l3cd = + nm_device_create_l3_config_data_from_connection(self, + nm_device_get_applied_connection(self)); } - r = sd_ipv4ll_start(priv->ipv4ll); - if (r < 0) { - _LOGE(LOGD_AUTOIP4, "IPv4LL: start() failed with error %d", r); - return NM_ACT_STAGE_RETURN_FAILURE; + if (!l3cd) { + _dev_ipmanual_cleanup(self); + return; } - _LOGI(LOGD_DEVICE | LOGD_AUTOIP4, "IPv4LL: started"); + /* Initially we set the state to pending, because we (maybe) have to perform ACD first. */ + _dev_ipmanual_set_state(self, AF_UNSPEC, NM_DEVICE_IP_STATE_PENDING); + + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_MANUALIP, l3cd, FALSE); - /* Start a timeout to bound the address attempt */ - priv->ipv4ll_timeout = g_timeout_add_seconds(20, ipv4ll_timeout_cb, self); - return NM_ACT_STAGE_RETURN_POSTPONE; + _dev_ip_state_check_async(self, AF_UNSPEC); } /*****************************************************************************/ static void -ensure_con_ip_config(NMDevice *self, int addr_family) +_dev_ipdhcpx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMIPConfig * con_ip_config; - if (priv->con_ip_config_x[IS_IPv4]) - return; - - connection = nm_device_get_applied_connection(self); - if (!connection) - return; + if (priv->ipdhcp_data_x[IS_IPv4].state != state) { + _LOGD_ipdhcp(addr_family, + "set state %s (was %s)", + nm_device_ip_state_to_string(state), + nm_device_ip_state_to_string(priv->ipdhcp_data_x[IS_IPv4].state)); + priv->ipdhcp_data_x[IS_IPv4].state = state; + } +} - con_ip_config = nm_device_ip_config_new(self, addr_family); +static void +_dev_ipdhcpx_cleanup(NMDevice *self, int addr_family, gboolean full_cleanup, gboolean release) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - if (IS_IPv4) { - nm_ip4_config_merge_setting(NM_IP4_CONFIG(con_ip_config), - nm_connection_get_setting_ip4_config(connection), - _prop_get_connection_mdns(self), - _prop_get_connection_llmnr(self), - _prop_get_connection_dns_over_tls(self), - nm_device_get_route_table(self, addr_family), - nm_device_get_route_metric(self, addr_family)); - } else { - nm_ip6_config_merge_setting(NM_IP6_CONFIG(con_ip_config), - nm_connection_get_setting_ip6_config(connection), - nm_device_get_route_table(self, addr_family), - nm_device_get_route_metric(self, addr_family)); - } + _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE); - if (nm_device_sys_iface_state_is_external_or_assume(self)) { - /* For assumed connections ignore all addresses and routes. */ - nm_ip_config_reset_addresses(con_ip_config); - nm_ip_config_reset_routes(con_ip_config); + if (full_cleanup && !IS_IPv4) { + priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE; + priv->ipdhcp_data_6.v6.needed_prefixes = 0; } - priv->con_ip_config_x[IS_IPv4] = con_ip_config; -} - -/*****************************************************************************/ + if (full_cleanup) + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), NULL, FALSE); -static const char * -_device_get_dhcp_anycast_address(NMDevice *self) -{ - NMDeviceClass *klass; - - nm_assert(NM_IS_DEVICE(self)); + if (priv->ipdhcp_data_x[IS_IPv4].client) { + nm_clear_g_signal_handler(priv->ipdhcp_data_x[IS_IPv4].client, + &priv->ipdhcp_data_x[IS_IPv4].notify_sigid); + nm_dhcp_client_stop(priv->ipdhcp_data_x[IS_IPv4].client, release); + g_clear_object(&priv->ipdhcp_data_x[IS_IPv4].client); + } - klass = NM_DEVICE_GET_CLASS(self); + if (full_cleanup && priv->ipdhcp_data_x[IS_IPv4].config) { + gs_unref_object NMDhcpConfig *config = + g_steal_pointer(&priv->ipdhcp_data_x[IS_IPv4].config); - if (klass->get_dhcp_anycast_address) - return klass->get_dhcp_anycast_address(self); + _notify(self, PROP_DHCPX_CONFIG(IS_IPv4)); + nm_dbus_object_unexport_on_idle(g_steal_pointer(&config)); + } - return NULL; + _dev_ip_state_check_async(self, addr_family); } static void -dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release) +_dev_ipdhcpx_handle_fail(NMDevice *self, int addr_family, const char *reason) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - priv->dhcp_data_4.was_active = FALSE; - nm_clear_g_source(&priv->dhcp_data_4.grace_id); - priv->dhcp_data_4.grace_pending = FALSE; - nm_clear_g_free(&priv->dhcp4.pac_url); + if (priv->ipdhcp_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_FAILED) + return; - if (priv->dhcp_data_4.client) { - /* Stop any ongoing DHCP transaction on this device */ - nm_clear_g_signal_handler(priv->dhcp_data_4.client, &priv->dhcp_data_4.notify_sigid); + _LOGT_ipdhcp(addr_family, "DHCP failing: %s", reason ?: "unknown reason"); - if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) - nm_dhcp_client_stop(priv->dhcp_data_4.client, release); + _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_FAILED); - g_clear_object(&priv->dhcp_data_4.client); - } + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), NULL, FALSE); - if (priv->dhcp_data_4.config) { - nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config); - _notify(self, PROP_DHCP4_CONFIG); - } + if (priv->ipdhcp_data_x[IS_IPv4].config) + nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, NULL); + + _dev_ip_state_check_async(self, addr_family); } -static gboolean -ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit) +static void +_dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gboolean success; - gs_unref_object NMIPConfig *composite = NULL; - NMIPConfig * config; - gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL; - NMConnection * connection; - gboolean ignore_auto_routes = FALSE; - gboolean ignore_auto_dns = FALSE; - gboolean ignore_default_routes = FALSE; - GSList * iter; - const char * ip6_addr_gen_token = NULL; - const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int addr_family = nm_dhcp_client_get_addr_family(client); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - if (nm_device_sys_iface_state_is_external(self)) - commit = FALSE; + nm_assert(notify_data); + nm_assert(priv->ipdhcp_data_x[IS_IPv4].state > NM_DEVICE_IP_STATE_NONE); + nm_assert(client && priv->ipdhcp_data_x[IS_IPv4].client == client); - connection = nm_device_get_applied_connection(self); + switch (notify_data->notify_type) { + case NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED: + nm_assert(!IS_IPv4); + /* Just re-emit. The device just contributes the prefix to the + * pool in NMPolicy, which decides about subnet allocation + * on the shared devices. */ + g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, notify_data->prefix_delegated.prefix); + return; - /* Apply ignore-auto-routes and ignore-auto-dns settings */ - if (connection) { - NMSettingIPConfig *s_ip; + case NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT: + /* Here we also fail if we had a lease and it expired. Maybe, + * ipv[46].dhcp-timeout should only cover the time until we get + * a lease for the first time. How it is here, it means that a + * connection can fail after being connected successfully for a + * longer time. */ + _dev_ipdhcpx_handle_fail(self, addr_family, "timeout getting lease"); + return; - s_ip = nm_connection_get_setting_ip_config(connection, addr_family); - if (s_ip) { - ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes(s_ip); - ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns(s_ip); + case NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD: + /* Like NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT, this does not + * apply only if we never got a lease, but also after being fully + * connected. We can also fail then. */ + _dev_ipdhcpx_handle_fail(self, addr_family, notify_data->it_looks_bad.reason); + return; - /* if the connection has an explicit gateway, we also ignore - * the default routes from other sources. */ - ignore_default_routes = nm_setting_ip_config_get_never_default(s_ip) - || nm_setting_ip_config_get_gateway(s_ip); + case NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE: - if (!IS_IPv4) { - NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG(s_ip); + if (!notify_data->lease_update.l3cd) { + _LOGT_ipdhcp(addr_family, "lease lost"); + goto lease_update_out; + } - if (nm_setting_ip6_config_get_addr_gen_mode(s_ip6) - == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) - ip6_addr_gen_token = nm_setting_ip6_config_get_token(s_ip6); + if (notify_data->lease_update.accepted) + _LOGT_ipdhcp(addr_family, "lease accepted"); + else + _LOGT_ipdhcp(addr_family, "lease update"); + + nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, + notify_data->lease_update.l3cd); + + /* Schedule a commit of the configuration. If the DHCP client + * needs to accept the lease, it will send later a LEASE_UPDATE + * notification with accepted=1 once the address appears in platform. + * Otherwise, this notification already has accepted=1. */ + _dev_l3_register_l3cds_set_one_full(self, + L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), + notify_data->lease_update.l3cd, + NM_L3CFG_CONFIG_FLAGS_FORCE_ONCE, + FALSE); + + if (notify_data->lease_update.accepted) { + if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_READY) { + _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY); + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4), + self, + NULL, + NULL, + NULL, + NULL); + _dev_ip_state_check_async(self, addr_family); } } - } - composite = nm_device_ip_config_new(self, addr_family); - - if (!IS_IPv4) { - nm_ip6_config_set_privacy(NM_IP6_CONFIG(composite), - priv->ndisc ? priv->ndisc_use_tempaddr - : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); +lease_update_out: + nm_device_update_metered(self); + return; } - init_ip_config_dns_priority(self, composite); - - if (commit) { - if (priv->queued_ip_config_id_x[IS_IPv4]) - update_ext_ip_config(self, addr_family, FALSE); - ensure_con_ip_config(self, addr_family); - } + nm_assert_not_reached(); +} - if (!IS_IPv4) { - if (commit && priv->ipv6ll_has) { - const NMPlatformIP6Address ll_a = { - .address = priv->ipv6ll_addr, - .plen = 64, - .addr_source = NM_IP_CONFIG_SOURCE_IP6LL, - }; - const NMPlatformIP6Route ll_r = { - .network.s6_addr16[0] = htons(0xfe80u), - .plen = 64, - .metric = nm_device_get_route_metric(self, addr_family), - .rt_source = NM_IP_CONFIG_SOURCE_IP6LL, - }; +/*****************************************************************************/ - nm_assert(IN6_IS_ADDR_LINKLOCAL(&priv->ipv6ll_addr)); +static void +_dev_ipdhcpx_start(NMDevice *self, int addr_family) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingIPConfig *s_ip; + const NML3ConfigData *previous_lease; + gs_unref_bytes GBytes *hwaddr = NULL; + gboolean enforce_duid = FALSE; + gs_free_error GError *error = NULL; + const NMPlatformLink *pllink; + guint no_lease_timeout_sec; + int ifindex; + const char *str; + gboolean request_broadcast; + const char *fail_reason; - nm_ip6_config_add_address(NM_IP6_CONFIG(composite), &ll_a); - nm_ip6_config_add_route(NM_IP6_CONFIG(composite), &ll_r, NULL); - } + if (priv->ipdhcp_data_x[IS_IPv4].state == NM_DEVICE_IP_STATE_NONE) + _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_PENDING); + else if (priv->ipdhcp_data_x[IS_IPv4].state > NM_DEVICE_IP_STATE_PENDING) { + /* already succeeded or failed */ + return; + } else if (priv->ipdhcp_data_x[IS_IPv4].client) { + /* DHCP client already started */ + return; } - if (commit) { - gboolean v; + if (nm_device_sys_iface_state_is_external(self)) { + fail_reason = nm_assert_unreachable_val("cannot run DHCP on external interface"); + goto out_fail; + } - v = default_route_metric_penalty_detect(self, addr_family); - if (IS_IPv4) - priv->default_route_metric_penalty_ip4_has = v; - else - priv->default_route_metric_penalty_ip6_has = v; + connection = nm_device_get_applied_connection(self); + if (!connection) { + fail_reason = nm_assert_unreachable_val("no applied connection for starting DHCP"); + goto out_fail; } - /* Merge all the IP configs into the composite config */ + s_con = nm_connection_get_setting_connection(connection); + s_ip = nm_connection_get_setting_ip_config(connection, addr_family); + nm_assert(s_con); + nm_assert(s_ip); - if (IS_IPv4) { - config = applied_config_get_current(&priv->dev_ip_config_4); - if (config) { - nm_ip4_config_merge( - NM_IP4_CONFIG(composite), - NM_IP4_CONFIG(config), - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get(self, addr_family)); - } + ifindex = 0; + pllink = nm_l3cfg_get_pllink(priv->l3cfg, TRUE); + if (pllink) { + ifindex = pllink->ifindex; + nm_assert(ifindex > 0); + nm_assert(ifindex == nm_device_get_ip_ifindex(self)); } - - if (!IS_IPv4) { - config = applied_config_get_current(&priv->ac_ip6_config); - if (config) { - nm_ip6_config_merge( - NM_IP6_CONFIG(composite), - NM_IP6_CONFIG(config), - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get(self, addr_family)); - } + if (ifindex <= 0) { + fail_reason = "cannot start DHCP without interface"; + goto out_fail; } + hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address); + if (!IS_IPv4) { - config = applied_config_get_current(&priv->dhcp6.ip6_config); - if (config) { - nm_ip6_config_merge( - NM_IP6_CONFIG(composite), - NM_IP6_CONFIG(config), - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get(self, addr_family)); + if (!hwaddr) { + fail_reason = "interface has no MAC address to start DHCPv6"; + goto out_fail; } } - for (iter = priv->vpn_configs_x[IS_IPv4]; iter; iter = iter->next) - nm_ip_config_merge(composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); - - if (priv->ext_ip_config_x[IS_IPv4]) - nm_ip_config_merge(composite, - priv->ext_ip_config_x[IS_IPv4], - NM_IP_CONFIG_MERGE_EXTERNAL, - 0); - - /* Merge WWAN config *last* to ensure modem-given settings overwrite - * any external stuff set by pppd or other scripts. - */ - config = applied_config_get_current(&priv->dev2_ip_config_x[IS_IPv4]); - if (config) { - nm_ip_config_merge(composite, - config, - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get(self, addr_family)); - } - - if (!IS_IPv4) { - if (priv->rt6_temporary_not_available) { - const NMPObject *o; - GHashTableIter hiter; - - g_hash_table_iter_init(&hiter, priv->rt6_temporary_not_available); - while (g_hash_table_iter_next(&hiter, (gpointer *) &o, NULL)) { - nm_ip6_config_add_route(NM_IP6_CONFIG(composite), - NMP_OBJECT_CAST_IP6_ROUTE(o), - NULL); - } + request_broadcast = FALSE; + if (pllink) { + str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink), + "ID_NET_DHCP_BROADCAST"); + if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) { + /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces + * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast + * messages while not fully configured. + */ + request_broadcast = TRUE; } } - /* Merge user overrides into the composite config. For assumed connections, - * con_ip_config_x is empty. */ - if (priv->con_ip_config_x[IS_IPv4]) { - nm_ip_config_merge(composite, - priv->con_ip_config_x[IS_IPv4], - NM_IP_CONFIG_MERGE_DEFAULT, - default_route_metric_penalty_get(self, addr_family)); + if (!IS_IPv4 + && NM_IN_SET(priv->ipll_data_6.state, + NM_DEVICE_IP_STATE_NONE, + NM_DEVICE_IP_STATE_PENDING)) { + _dev_ipll6_start(self); + return; } - if (commit) { - gboolean is_vrf; + no_lease_timeout_sec = _prop_get_ipvx_dhcp_timeout(self, addr_family); - is_vrf = priv->master && nm_device_get_device_type(priv->master) == NM_DEVICE_TYPE_VRF; + if (IS_IPv4) { + NMDhcpClientConfig config; + gs_unref_bytes GBytes *bcast_hwaddr = NULL; + gs_unref_bytes GBytes *client_id = NULL; + gs_unref_bytes GBytes *vendor_class_identifier = NULL; + const char *const *reject_servers; + const char *hostname; + gboolean hostname_is_fqdn; + + client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr); + vendor_class_identifier = + _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip)); + reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip, NULL); + + bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast); - if (IS_IPv4) { - nm_ip4_config_add_dependent_routes(NM_IP4_CONFIG(composite), - nm_device_get_route_table(self, addr_family), - nm_device_get_route_metric(self, addr_family), - is_vrf, - &ip4_dev_route_blacklist); + hostname = nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip)); + if (hostname) { + hostname_is_fqdn = TRUE; } else { - nm_ip6_config_add_dependent_routes(NM_IP6_CONFIG(composite), - nm_device_get_route_table(self, addr_family), - nm_device_get_route_metric(self, addr_family), - is_vrf); + hostname_is_fqdn = FALSE; + hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip); } - } - if (IS_IPv4) { - if (commit) { - if (NM_DEVICE_GET_CLASS(self)->ip4_config_pre_commit) - NM_DEVICE_GET_CLASS(self)->ip4_config_pre_commit(self, NM_IP4_CONFIG(composite)); - } - } + config = (NMDhcpClientConfig){ + .addr_family = AF_INET, + .l3cfg = nm_device_get_l3cfg(self), + .iface = nm_device_get_ip_iface(self), + .uuid = nm_connection_get_uuid(connection), + .hwaddr = hwaddr, + .bcast_hwaddr = bcast_hwaddr, + .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip), + .hostname = hostname, + .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET), + .client_id = client_id, + .mud_url = _prop_get_connection_mud_url(self, s_con), + .timeout = no_lease_timeout_sec, + .anycast_address = _device_get_dhcp_anycast_address(self), + .vendor_class_identifier = vendor_class_identifier, + .use_fqdn = hostname_is_fqdn, + .reject_servers = reject_servers, + .v4.request_broadcast = request_broadcast, + }; - if (!IS_IPv4) { - NMUtilsIPv6IfaceId iid; + priv->ipdhcp_data_4.client = + nm_dhcp_manager_start_client(nm_dhcp_manager_get(), &config, &error); + } else { + gs_unref_bytes GBytes *duid = NULL; + gboolean iaid_explicit; + guint32 iaid; + NMDhcpClientConfig config; + + iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, FALSE, &iaid_explicit); + duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid); + + config = (NMDhcpClientConfig){ + .addr_family = AF_INET6, + .l3cfg = nm_device_get_l3cfg(self), + .iface = nm_device_get_ip_iface(self), + .uuid = nm_connection_get_uuid(connection), + .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip), + .hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip), + .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6), + .client_id = duid, + .mud_url = _prop_get_connection_mud_url(self, s_con), + .timeout = no_lease_timeout_sec, + .anycast_address = _device_get_dhcp_anycast_address(self), + .v6.enforce_duid = enforce_duid, + .v6.iaid = iaid, + .v6.iaid_explicit = iaid_explicit, + .v6.info_only = (priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF), + .v6.needed_prefixes = priv->ipdhcp_data_6.v6.needed_prefixes, + }; - if (commit && priv->ndisc_started && ip6_addr_gen_token - && nm_utils_ipv6_interface_identifier_get_from_token(&iid, ip6_addr_gen_token)) { - set_ipv6_token(self, &iid, ip6_addr_gen_token); - } + priv->ipdhcp_data_6.client = + nm_dhcp_manager_start_client(nm_dhcp_manager_get(), &config, &error); } - success = - nm_device_set_ip_config(self, addr_family, composite, commit, ip4_dev_route_blacklist); - if (commit) { - if (IS_IPv4) - priv->v4_commit_first_time = FALSE; - else - priv->v6_commit_first_time = FALSE; + if (!priv->ipdhcp_data_x[IS_IPv4].client) { + fail_reason = error->message; + goto out_fail; } - return success; -} - -static gboolean -dhcp4_lease_change(NMDevice *self, NMIP4Config *config, gboolean bound) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gs_free_error GError *error = NULL; - - g_return_val_if_fail(config, FALSE); + priv->ipdhcp_data_x[IS_IPv4].notify_sigid = + g_signal_connect(priv->ipdhcp_data_x[IS_IPv4].client, + NM_DHCP_CLIENT_NOTIFY, + G_CALLBACK(_dev_ipdhcpx_notify), + self); - applied_config_init(&priv->dev_ip_config_4, config); + /* FIXME(l3cfg:dhcp:previous-lease): take the NML3ConfigData from the previous lease (if any) + * and pass it on to NMDhcpClient. This is a fake lease that we use initially (until + * NMDhcpClient got a real lease). Note that NMDhcpClient needs to check whether the + * lease already expired. */ - if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) { - _LOGW(LOGD_DHCP4, "failed to update IPv4 config for DHCP change."); - return FALSE; + previous_lease = nm_dhcp_client_get_lease(priv->ipdhcp_data_x[IS_IPv4].client); + if (!priv->ipdhcp_data_x[IS_IPv4].config) { + priv->ipdhcp_data_x[IS_IPv4].config = nm_dhcp_config_new(addr_family, previous_lease); + _notify(self, PROP_DHCPX_CONFIG(IS_IPv4)); } - - /* TODO: we should perform DAD again whenever we obtain a - * new lease after an expiry. But what should we do if - * a duplicate address is detected? Fail the connection; - * restart DHCP; continue without an address? */ - if (bound && !nm_dhcp_client_accept(priv->dhcp_data_4.client, &error)) { - _LOGW(LOGD_DHCP4, "error accepting lease: %s", error->message); - return FALSE; + if (previous_lease) { + nm_dhcp_config_set_lease(priv->ipdhcp_data_x[IS_IPv4].config, previous_lease); + _dev_l3_register_l3cds_set_one_full(self, + L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), + previous_lease, + NM_L3CFG_CONFIG_FLAGS_FORCE_ONCE, + FALSE); } - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, self, NULL, NULL, NULL, NULL); + return; - return TRUE; +out_fail: + _dev_ipdhcpx_handle_fail(self, addr_family, fail_reason); } -static gboolean -dhcp_grace_period_expired(NMDevice *self, int addr_family) +static void +_dev_ipdhcpx_start_continue(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const int IS_IPv4 = NM_IS_IPv4(addr_family); - priv->dhcp_data_x[IS_IPv4].grace_id = 0; - priv->dhcp_data_x[IS_IPv4].grace_pending = FALSE; - - _LOGI(LOGD_DHCPX(IS_IPv4), - "DHCPv%c: grace period expired", - nm_utils_addr_family_to_char(addr_family)); - - nm_device_ip_method_failed(self, addr_family, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - /* If the device didn't fail, the DHCP client will continue */ - - return G_SOURCE_REMOVE; -} - -static gboolean -dhcp_grace_period_expired_4(gpointer user_data) -{ - return dhcp_grace_period_expired(user_data, AF_INET); -} - -static gboolean -dhcp_grace_period_expired_6(gpointer user_data) -{ - return dhcp_grace_period_expired(user_data, AF_INET6); + if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_NONE) + _dev_ipdhcpx_start(self, addr_family); } -static gboolean -dhcp_grace_period_start(NMDevice *self, int addr_family) +static void +_dev_ipdhcpx_restart(NMDevice *self, int addr_family, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); const int IS_IPv4 = NM_IS_IPv4(addr_family); - guint32 timeout; - - /* In any other case (expired lease, assumed connection, etc.), - * wait for some time before failing the IP method. - */ - if (priv->dhcp_data_x[IS_IPv4].grace_pending) { - /* already pending. */ - return FALSE; - } - /* Start a grace period equal to the DHCP timeout multiplied - * by a constant factor. */ - timeout = _prop_get_ipvx_dhcp_timeout(self, addr_family); - if (timeout == NM_DHCP_TIMEOUT_INFINITY) - _LOGI(LOGD_DHCPX(IS_IPv4), - "DHCPv%c: trying to acquire a new lease", - nm_utils_addr_family_to_char(addr_family)); - else { - timeout = dhcp_grace_period_from_timeout(timeout); - _LOGI(LOGD_DHCPX(IS_IPv4), - "DHCPv%c: trying to acquire a new lease within %u seconds", - nm_utils_addr_family_to_char(addr_family), - timeout); - nm_assert(!priv->dhcp_data_x[IS_IPv4].grace_id); - priv->dhcp_data_x[IS_IPv4].grace_id = g_timeout_add_seconds( - timeout, - IS_IPv4 ? dhcp_grace_period_expired_4 : dhcp_grace_period_expired_6, - self); + if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_NONE) { + _LOGI_ipdhcp(addr_family, "restarting%s", release ? " (release lease)" : ""); + _dev_ipdhcpx_cleanup(self, addr_family, FALSE, release); } - priv->dhcp_data_x[IS_IPv4].grace_pending = TRUE; - - return TRUE; + _dev_ipdhcpx_start(self, addr_family); } -static void -dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - _LOGD(LOGD_DHCP4, - "DHCPv4 failed (ip_state %s, was_active %d)", - nm_device_ip_state_to_string(priv->ip_state_4), - priv->dhcp_data_4.was_active); - /* The client is always left running after a failure. */ - - /* Nothing to do if we failed before... */ - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL) - goto clear_config; - - /* ... and also if there are static addresses configured - * on the interface. - */ - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && priv->con_ip_config_4 - && nm_ip4_config_get_num_addresses(priv->con_ip_config_4) > 0) - goto clear_config; - - /* Fail the method when one of the following is true: - * 1) the DHCP client terminated: it does not make sense to start a grace - * period without a client running; - * 2) we failed to get an initial lease AND the client was - * not active before. - */ - if (dhcp_state == NM_DHCP_STATE_TERMINATED - || (!priv->dhcp_data_4.was_active && priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)) { - nm_device_activate_schedule_ip_config_timeout(self, AF_INET); - return; - } - - if (dhcp_grace_period_start(self, AF_INET)) - goto clear_config; - - return; - -clear_config: - /* The previous configuration is no longer valid */ - if (priv->dhcp_data_4.config) { - nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config); - priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET); - _notify(self, PROP_DHCP4_CONFIG); - } -} - -static void -dhcp4_dad_cb(NMDevice *self, NMIP4Config **configs, gboolean success) +void +nm_device_ip_method_dhcp4_start(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - if (success) { - nm_device_activate_schedule_ip_config_result(self, AF_INET, NM_IP_CONFIG_CAST(configs[1])); - } else { - nm_dhcp_client_decline(priv->dhcp_data_4.client, "Address conflict detected", NULL); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE); - } + _dev_ipdhcpx_start(self, AF_INET); } static void -dhcp4_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) +_dev_ipdhcp6_set_dhcp_level(NMDevice *self, NMNDiscDHCPLevel dhcp_level) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMIP4Config * manual; - NMIP4Config ** configs; - NMConnection * connection; - NMDhcpState state; - NMIP4Config * ip4_config; - GHashTable * options; - - nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET); - nm_assert(notify_data); - nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED); - state = notify_data->state_changed.dhcp_state; - ip4_config = NM_IP4_CONFIG(notify_data->state_changed.ip_config); - options = notify_data->state_changed.options; + nm_assert(NM_IN_SET(dhcp_level, + NM_NDISC_DHCP_LEVEL_NONE, + NM_NDISC_DHCP_LEVEL_OTHERCONF, + NM_NDISC_DHCP_LEVEL_MANAGED)); - nm_assert(!ip4_config || NM_IS_IP4_CONFIG(ip4_config)); + if (dhcp_level == NM_NDISC_DHCP_LEVEL_NONE && priv->ipdhcp_data_6.v6.needed_prefixes > 0) + dhcp_level = NM_NDISC_DHCP_LEVEL_OTHERCONF; - _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", (int) state); - - switch (state) { - case NM_DHCP_STATE_BOUND: - case NM_DHCP_STATE_EXTENDED: - if (!ip4_config) { - _LOGW(LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event."); - dhcp4_fail(self, state); - break; - } - - nm_clear_g_source(&priv->dhcp_data_4.grace_id); - priv->dhcp_data_4.grace_pending = FALSE; - - /* After some failures, we have been able to renew the lease: - * update the ip state - */ - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL) - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_CONF); - - g_free(priv->dhcp4.pac_url); - priv->dhcp4.pac_url = g_strdup(g_hash_table_lookup(options, "wpad")); - nm_device_set_proxy_config(self, priv->dhcp4.pac_url); - - nm_dhcp_config_set_options(priv->dhcp_data_4.config, options); - _notify(self, PROP_DHCP4_CONFIG); - - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) { - connection = nm_device_get_applied_connection(self); - g_assert(connection); - - manual = nm_device_ip4_config_new(self); - nm_ip4_config_merge_setting(manual, - nm_connection_get_setting_ip4_config(connection), - NM_SETTING_CONNECTION_MDNS_DEFAULT, - NM_SETTING_CONNECTION_LLMNR_DEFAULT, - NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, - nm_device_get_route_table(self, AF_INET), - nm_device_get_route_metric(self, AF_INET)); - - configs = g_new0(NMIP4Config *, 3); - configs[0] = manual; - configs[1] = g_object_ref(ip4_config); - - ipv4_dad_start(self, configs, dhcp4_dad_cb); - } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) { - if (dhcp4_lease_change(self, ip4_config, state == NM_DHCP_STATE_BOUND)) - nm_device_update_metered(self); - else - dhcp4_fail(self, state); - } - break; - case NM_DHCP_STATE_TIMEOUT: - dhcp4_fail(self, state); - break; - case NM_DHCP_STATE_EXPIRE: - /* Ignore expiry before we even have a lease (NAK, old lease, etc) */ - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) - break; - /* fall-through */ - case NM_DHCP_STATE_DONE: - case NM_DHCP_STATE_FAIL: - case NM_DHCP_STATE_TERMINATED: - dhcp4_fail(self, state); - break; - default: - break; - } -} - -static NMActStageReturn -dhcp4_start(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMSettingIPConfig *s_ip4; - gs_unref_bytes GBytes *vendor_class_identifier = NULL; - gs_unref_bytes GBytes *hwaddr = NULL; - gs_unref_bytes GBytes *bcast_hwaddr = NULL; - gs_unref_bytes GBytes *client_id = NULL; - NMConnection * connection; - NMSettingConnection * s_con; - GError * error = NULL; - const NMPlatformLink * pllink; - const char *const * reject_servers; - gboolean request_broadcast; - const char * str; - - connection = nm_device_get_applied_connection(self); - g_return_val_if_fail(connection, FALSE); - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - - s_con = nm_connection_get_setting_connection(connection); - nm_assert(s_con); - - /* Clear old exported DHCP options */ - nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config); - priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET); - - request_broadcast = FALSE; + if (priv->ipdhcp_data_6.v6.mode == dhcp_level) + return; - pllink = nm_platform_link_get(nm_device_get_platform(self), nm_device_get_ip_ifindex(self)); - if (pllink) { - hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address); - bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast); + _LOGD_ipdhcp(AF_INET6, "level: set to %s", nm_ndisc_dhcp_level_to_string(dhcp_level)); - str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink), - "ID_NET_DHCP_BROADCAST"); - if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) { - /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces - * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast - * messages while not fully configured. - */ - request_broadcast = TRUE; - } + if (dhcp_level == NM_NDISC_DHCP_LEVEL_NONE) { + _dev_ipdhcpx_cleanup(self, AF_INET6, TRUE, TRUE); + return; } - client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr); - vendor_class_identifier = - _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip4)); - reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip4, NULL); - - g_warn_if_fail(priv->dhcp_data_4.client == NULL); - priv->dhcp_data_4.client = nm_dhcp_manager_start_ip4( - nm_dhcp_manager_get(), - nm_netns_get_multi_idx(nm_device_get_netns(self)), - nm_device_get_ip_iface(self), - nm_device_get_ip_ifindex(self), - hwaddr, - bcast_hwaddr, - nm_connection_get_uuid(connection), - nm_device_get_route_table(self, AF_INET), - nm_device_get_route_metric(self, AF_INET), - request_broadcast ? NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST : NM_DHCP_CLIENT_FLAGS_NONE, - nm_setting_ip_config_get_dhcp_send_hostname(s_ip4), - nm_setting_ip_config_get_dhcp_hostname(s_ip4), - nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)), - _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET), - _prop_get_connection_mud_url(self, s_con), - client_id, - _prop_get_ipvx_dhcp_timeout(self, AF_INET), - _device_get_dhcp_anycast_address(self), - NULL, - vendor_class_identifier, - reject_servers, - &error); - if (!priv->dhcp_data_4.client) { - _LOGW(LOGD_DHCP4, "failure to start DHCP: %s", error->message); - g_clear_error(&error); - return NM_ACT_STAGE_RETURN_FAILURE; - } - - priv->dhcp_data_4.notify_sigid = g_signal_connect(priv->dhcp_data_4.client, - NM_DHCP_CLIENT_NOTIFY, - G_CALLBACK(dhcp4_notify), - self); - - if (nm_device_sys_iface_state_is_external_or_assume(self)) - priv->dhcp_data_4.was_active = TRUE; - - /* DHCP devices will be notified by the DHCP manager when stuff happens */ - return NM_ACT_STAGE_RETURN_POSTPONE; + priv->ipdhcp_data_6.v6.mode = dhcp_level; + _dev_ipdhcpx_restart(self, AF_INET6, TRUE); } -gboolean -nm_device_dhcp4_renew(NMDevice *self, gboolean release) +/* + * Called on the requesting interface when a subnet can't be obtained + * from known prefixes for a newly active shared connection. + */ +void +nm_device_request_ip6_prefixes(NMDevice *self, guint needed_prefixes) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - g_return_val_if_fail(priv->dhcp_data_4.client != NULL, FALSE); - - _LOGI(LOGD_DHCP4, "DHCPv4 lease renewal requested"); - - /* Terminate old DHCP instance and release the old lease */ - dhcp4_cleanup(self, CLEANUP_TYPE_DECONFIGURE, release); - - /* Start DHCP again on the interface */ - return dhcp4_start(self) != NM_ACT_STAGE_RETURN_FAILURE; -} - -/*****************************************************************************/ + if (priv->ipdhcp_data_6.v6.needed_prefixes == needed_prefixes) + return; -static NMIP4Config * -shared4_new_config(NMDevice *self, NMConnection *connection) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMIP4Config * config; - NMSettingIPConfig * s_ip4; - NMPlatformIP4Address address = { - .addr_source = NM_IP_CONFIG_SOURCE_SHARED, - }; + _LOGD(LOGD_IP6, "ipv6-pd: asking DHCPv6 for %u prefixes", needed_prefixes); - g_return_val_if_fail(self, NULL); - g_return_val_if_fail(connection, NULL); + priv->ipdhcp_data_6.v6.needed_prefixes = needed_prefixes; - s_ip4 = nm_connection_get_setting_ip4_config(connection); - if (s_ip4 && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) { - /* Use the first user-supplied address */ - NMIPAddress *user = nm_setting_ip_config_get_address(s_ip4, 0); - in_addr_t a; - - nm_ip_address_get_address_binary(user, &a); - nm_platform_ip4_address_set_addr(&address, a, nm_ip_address_get_prefix(user)); - nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release); - } else { - if (!priv->shared_ip_handle) - priv->shared_ip_handle = nm_netns_shared_ip_reserve(nm_device_get_netns(self)); - nm_platform_ip4_address_set_addr(&address, priv->shared_ip_handle->addr, 24); + if (priv->ipdhcp_data_6.v6.mode == NM_NDISC_DHCP_LEVEL_NONE) { + priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_OTHERCONF; + _LOGD_ipdhcp(AF_INET6, + "level: set to %s", + nm_ndisc_dhcp_level_to_string(NM_NDISC_DHCP_LEVEL_OTHERCONF)); } - config = nm_device_ip4_config_new(self); - nm_ip4_config_add_address(config, &address); - - return config; + _dev_ipdhcpx_restart(self, AF_INET6, TRUE); } /*****************************************************************************/ @@ -9710,7 +10303,7 @@ shared4_new_config(NMDevice *self, NMConnection *connection) static gboolean connection_ip_method_requires_carrier(NMConnection *connection, int addr_family, - gboolean * out_ip_enabled) + gboolean *out_ip_enabled) { const char *method; @@ -9737,7 +10330,7 @@ connection_ip_method_requires_carrier(NMConnection *connection, static gboolean connection_requires_carrier(NMConnection *connection) { - NMSettingIPConfig * s_ip4, *s_ip6; + NMSettingIPConfig *s_ip4, *s_ip6; NMSettingConnection *s_con; gboolean ip4_carrier_wanted, ip6_carrier_wanted; gboolean ip4_used = FALSE, ip6_used = FALSE; @@ -9784,8 +10377,8 @@ static gboolean have_any_ready_slaves(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - SlaveInfo * info; - CList * iter; + SlaveInfo *info; + CList *iter; /* Any enslaved slave is "ready" in the generic case as it's * at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2 @@ -9800,392 +10393,6 @@ have_any_ready_slaves(NMDevice *self) } /*****************************************************************************/ -/* DHCPv6 stuff */ - -static void -dhcp6_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - priv->dhcp_data_6.was_active = FALSE; - priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE; - applied_config_clear(&priv->dhcp6.ip6_config); - nm_clear_g_free(&priv->dhcp6.event_id); - nm_clear_g_source(&priv->dhcp_data_6.grace_id); - priv->dhcp_data_6.grace_pending = FALSE; - - if (priv->dhcp_data_6.client) { - nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp_data_6.notify_sigid); - - if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) - nm_dhcp_client_stop(priv->dhcp_data_6.client, release); - - g_clear_object(&priv->dhcp_data_6.client); - } - - if (priv->dhcp_data_6.config) { - nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config); - _notify(self, PROP_DHCP6_CONFIG); - } -} - -static gboolean -dhcp6_lease_change(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMSettingsConnection *settings_connection; - - if (!applied_config_get_current(&priv->dhcp6.ip6_config)) { - _LOGW(LOGD_DHCP6, "failed to get DHCPv6 config for rebind"); - return FALSE; - } - - g_assert(priv->dhcp_data_6.client); /* sanity check */ - - settings_connection = nm_device_get_settings_connection(self); - g_assert(settings_connection); - - /* Apply the updated config */ - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) { - _LOGW(LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event"); - return FALSE; - } - - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, self, NULL, NULL, NULL, NULL); - - return TRUE; -} - -static void -dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gboolean is_dhcp_managed; - - _LOGD(LOGD_DHCP6, - "DHCPv6 failed (ip_state %s, was_active %d)", - nm_device_ip_state_to_string(priv->ip_state_6), - priv->dhcp_data_6.was_active); - - /* The client is always left running after a failure. */ - - /* Nothing to do if we failed before... */ - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL) - goto clear_config; - - is_dhcp_managed = (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED); - - if (is_dhcp_managed) { - /* ... and also if there are static addresses configured - * on the interface. - */ - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE && priv->con_ip_config_6 - && nm_ip6_config_get_num_addresses(priv->con_ip_config_6)) - goto clear_config; - - /* Fail the method when one of the following is true: - * 1) the DHCP client terminated: it does not make sense to start a grace - * period without a client running; - * 2) we failed to get an initial lease AND the client was - * not active before. - */ - if (dhcp_state == NM_DHCP_STATE_TERMINATED - || (!priv->dhcp_data_6.was_active && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)) { - nm_device_activate_schedule_ip_config_timeout(self, AF_INET6); - return; - } - - if (dhcp_grace_period_start(self, AF_INET6)) - goto clear_config; - } else { - /* not a hard failure; just live with the RA info */ - dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, FALSE); - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - } - return; - -clear_config: - /* The previous configuration is no longer valid */ - if (priv->dhcp_data_6.config) { - nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config); - priv->dhcp_data_6.config = nm_dhcp_config_new(AF_INET6); - _notify(self, PROP_DHCP6_CONFIG); - } -} - -static void -dhcp6_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gs_free char * event_id = NULL; - NMDhcpState state; - NMIP6Config * ip6_config; - GHashTable * options; - - nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET6); - nm_assert(notify_data); - - if (notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED) { - /* Just re-emit. The device just contributes the prefix to the - * pool in NMPolicy, which decides about subnet allocation - * on the shared devices. */ - g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, notify_data->prefix_delegated.prefix); - return; - } - - nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED); - - state = notify_data->state_changed.dhcp_state; - ip6_config = NM_IP6_CONFIG(notify_data->state_changed.ip_config); - options = notify_data->state_changed.options; - - nm_assert(!ip6_config || NM_IS_IP6_CONFIG(ip6_config)); - - _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", (int) state); - - switch (state) { - case NM_DHCP_STATE_BOUND: - case NM_DHCP_STATE_EXTENDED: - nm_clear_g_source(&priv->dhcp_data_6.grace_id); - priv->dhcp_data_6.grace_pending = FALSE; - /* If the server sends multiple IPv6 addresses, we receive a state - * changed event for each of them. Use the event ID to merge IPv6 - * addresses from the same transaction into a single configuration. - */ - - event_id = nm_dhcp_utils_get_dhcp6_event_id(options); - - if (ip6_config && event_id && priv->dhcp6.event_id - && nm_streq(event_id, priv->dhcp6.event_id)) { - NMDedupMultiIter ipconf_iter; - const NMPlatformIP6Address *a; - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6_config, &a) - applied_config_add_address(&priv->dhcp6.ip6_config, NM_PLATFORM_IP_ADDRESS_CAST(a)); - } else { - nm_clear_g_free(&priv->dhcp6.event_id); - if (ip6_config) { - applied_config_init(&priv->dhcp6.ip6_config, ip6_config); - priv->dhcp6.event_id = g_strdup(event_id); - nm_dhcp_config_set_options(priv->dhcp_data_6.config, options); - _notify(self, PROP_DHCP6_CONFIG); - } else - applied_config_clear(&priv->dhcp6.ip6_config); - } - - /* After long time we have been able to renew the lease: - * update the ip state - */ - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL) - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_CONF); - - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) { - if (!applied_config_get_current(&priv->dhcp6.ip6_config)) { - nm_device_ip_method_failed(self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED); - break; - } - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - } else if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) - if (!dhcp6_lease_change(self)) - dhcp6_fail(self, state); - break; - case NM_DHCP_STATE_TIMEOUT: - if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) - dhcp6_fail(self, state); - else { - /* not a hard failure; just live with the RA info */ - dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, FALSE); - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - } - break; - case NM_DHCP_STATE_EXPIRE: - /* Ignore expiry before we even have a lease (NAK, old lease, etc) */ - if (priv->ip_state_6 != NM_DEVICE_IP_STATE_CONF) - dhcp6_fail(self, state); - break; - case NM_DHCP_STATE_TERMINATED: - /* In IPv6 info-only mode, the client doesn't handle leases so it - * may exit right after getting a response from the server. That's - * normal. In that case we just ignore the exit. - */ - if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) - break; - /* fall-through */ - case NM_DHCP_STATE_DONE: - case NM_DHCP_STATE_FAIL: - dhcp6_fail(self, state); - break; - default: - break; - } -} - -/*****************************************************************************/ - -static gboolean -dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMSettingIPConfig *s_ip6; - gs_unref_bytes GBytes *hwaddr = NULL; - gs_unref_bytes GBytes * duid = NULL; - gboolean enforce_duid = FALSE; - const NMPlatformLink * pllink; - GError * error = NULL; - guint32 iaid; - gboolean iaid_explicit; - NMSettingConnection * s_con; - const NMPlatformIP6Address *ll_addr = NULL; - int ip_ifindex; - - g_return_val_if_fail(connection, FALSE); - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - nm_assert(s_ip6); - s_con = nm_connection_get_setting_connection(connection); - nm_assert(s_con); - - if (priv->ext_ip6_config_captured) { - ll_addr = nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL); - } - - if (!ll_addr) { - _LOGW(LOGD_DHCP6, "can't start DHCPv6: no link-local address"); - return FALSE; - } - - ip_ifindex = nm_device_get_ip_ifindex(self); - if (ip_ifindex <= 0) { - _LOGD(LOGD_DHCP6, "can't start DHCPv6: interface is gone"); - return FALSE; - } - - pllink = nm_platform_link_get(nm_device_get_platform(self), ip_ifindex); - if (pllink) - hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address); - - iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, TRUE, &iaid_explicit); - duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid); - - priv->dhcp_data_6.client = nm_dhcp_manager_start_ip6( - nm_dhcp_manager_get(), - nm_device_get_multi_index(self), - nm_device_get_ip_iface(self), - ip_ifindex, - &ll_addr->address, - nm_connection_get_uuid(connection), - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6), - (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY - : NM_DHCP_CLIENT_FLAGS_NONE, - nm_setting_ip_config_get_dhcp_send_hostname(s_ip6), - nm_setting_ip_config_get_dhcp_hostname(s_ip6), - _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6), - _prop_get_connection_mud_url(self, s_con), - duid, - enforce_duid, - iaid, - iaid_explicit, - _prop_get_ipvx_dhcp_timeout(self, AF_INET6), - _device_get_dhcp_anycast_address(self), - nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip6)), - priv->dhcp6.needed_prefixes, - &error); - if (!priv->dhcp_data_6.client) { - _LOGW(LOGD_DHCP6, "failure to start DHCPv6: %s", error->message); - g_clear_error(&error); - if (nm_device_sys_iface_state_is_external_or_assume(self)) - priv->dhcp_data_6.was_active = TRUE; - return FALSE; - } - - priv->dhcp_data_6.notify_sigid = g_signal_connect(priv->dhcp_data_6.client, - NM_DHCP_CLIENT_NOTIFY, - G_CALLBACK(dhcp6_notify), - self); - - if (nm_device_sys_iface_state_is_external_or_assume(self)) - priv->dhcp_data_6.was_active = TRUE; - - return TRUE; -} - -static gboolean -dhcp6_start(NMDevice *self, gboolean wait_for_ll) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; - - nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config); - priv->dhcp_data_6.config = nm_dhcp_config_new(AF_INET6); - - nm_assert(!applied_config_get_current(&priv->dhcp6.ip6_config)); - applied_config_clear(&priv->dhcp6.ip6_config); - nm_clear_g_free(&priv->dhcp6.event_id); - - connection = nm_device_get_applied_connection(self); - g_return_val_if_fail(connection, FALSE); - - if (wait_for_ll) { - /* ensure link local is ready... */ - if (!linklocal6_start(self)) { - /* wait for the LL address to show up */ - return TRUE; - } - /* already have the LL address; kick off DHCP */ - } - - if (!dhcp6_start_with_link_ready(self, connection)) - return FALSE; - - return TRUE; -} - -gboolean -nm_device_dhcp6_renew(NMDevice *self, gboolean release) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMNDiscDHCPLevel mode; - - g_return_val_if_fail(priv->dhcp_data_6.client != NULL, FALSE); - - _LOGI(LOGD_DHCP6, "DHCPv6 lease renewal requested"); - - /* Terminate old DHCP instance and release the old lease */ - mode = priv->dhcp6.mode; - dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, release); - priv->dhcp6.mode = mode; - - /* Start DHCP again on the interface */ - return dhcp6_start(self, FALSE); -} - -/*****************************************************************************/ - -/* - * Called on the requesting interface when a subnet can't be obtained - * from known prefixes for a newly active shared connection. - */ -void -nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - priv->dhcp6.needed_prefixes = needed_prefixes; - - if (priv->dhcp_data_6.client) { - _LOGD(LOGD_IP6, "ipv6-pd: asking DHCPv6 for %d prefixes", needed_prefixes); - nm_device_dhcp6_renew(self, FALSE); - } else { - priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_OTHERCONF; - _LOGD(LOGD_DEVICE | LOGD_DHCP6, "ipv6-pd: starting DHCPv6 to request a prefix"); - dhcp6_start(self, FALSE); - } -} gboolean nm_device_needs_ip6_subnet(NMDevice *self) @@ -10200,25 +10407,25 @@ nm_device_needs_ip6_subnet(NMDevice *self) void nm_device_use_ip6_subnet(NMDevice *self, const NMPlatformIP6Address *subnet) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMPlatformIP6Address address = *subnet; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + NMPlatformIP6Address address; - if (!applied_config_get_current(&priv->ac_ip6_config)) - applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6); + l3cd = nm_device_create_l3_config_data(self, NM_IP_CONFIG_SOURCE_SHARED); /* Assign a ::1 address in the subnet for us. */ + address = *subnet; address.address.s6_addr32[3] |= htonl(1); - applied_config_add_address(&priv->ac_ip6_config, NM_PLATFORM_IP_ADDRESS_CAST(&address)); + + nm_l3_config_data_add_address_6(l3cd, &address); _LOGD(LOGD_IP6, - "ipv6-pd: using %s address (preferred for %u seconds)", - _nm_utils_inet6_ntop(&address.address, sbuf), - subnet->preferred); + "ipv6-pd: using %s", + nm_platform_ip6_address_to_string(&address, sbuf, sizeof(sbuf))); - /* This also updates the ndisc if there are actual changes. */ - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing"); + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_PD_6, l3cd, FALSE); + _dev_l3_cfg_commit(self, TRUE); + _dev_ipac6_ndisc_set_router_config(self); } /* @@ -10228,217 +10435,231 @@ nm_device_use_ip6_subnet(NMDevice *self, const NMPlatformIP6Address *subnet) void nm_device_copy_ip6_dns_config(NMDevice *self, NMDevice *from_device) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMIP6Config * from_config = NULL; - guint i, len; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv_src; + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + const NML3ConfigData *l3cd_src = NULL; - if (applied_config_get_current(&priv->ac_ip6_config)) { - applied_config_reset_nameservers(&priv->ac_ip6_config); - applied_config_reset_searches(&priv->ac_ip6_config); - } else - applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6); + /* FIXME(l3cfg): this entire code an approach seems flawed. It's flawed, because the + * very next RA will reset the changes. */ - if (from_device) - from_config = nm_device_get_ip6_config(from_device); - if (!from_config) - return; + if (priv->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d) { + l3cd = nm_l3_config_data_new_clone(priv->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d, 0); + nm_l3_config_data_clear_nameservers(l3cd, AF_INET6); + nm_l3_config_data_clear_searches(l3cd, AF_INET6); + } else + l3cd = nm_device_create_l3_config_data(self, NM_IP_CONFIG_SOURCE_SHARED); - len = nm_ip6_config_get_num_nameservers(from_config); - for (i = 0; i < len; i++) { - applied_config_add_nameserver( - &priv->ac_ip6_config, - (const NMIPAddr *) nm_ip6_config_get_nameserver(from_config, i)); + if (from_device) { + priv_src = NM_DEVICE_GET_PRIVATE(from_device); + l3cd_src = priv_src->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d; } + if (l3cd_src) { + const char *const *strvarr; + const struct in6_addr *const *addrs; + guint n; + guint i; + + addrs = nm_l3_config_data_get_nameservers(l3cd_src, AF_INET6, &n); + for (i = 0; i < n; i++) + nm_l3_config_data_add_nameserver(l3cd, AF_INET6, addrs[i]); - len = nm_ip6_config_get_num_searches(from_config); - for (i = 0; i < len; i++) { - applied_config_add_search(&priv->ac_ip6_config, nm_ip6_config_get_search(from_config, i)); + strvarr = nm_l3_config_data_get_searches(l3cd_src, AF_INET6, &n); + for (i = 0; i < n; i++) + nm_l3_config_data_add_search(l3cd, AF_INET6, strvarr[i]); } - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing"); + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, l3cd, FALSE); + + _dev_l3_cfg_commit(self, TRUE); } /*****************************************************************************/ -static void -linklocal6_failed(NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - nm_clear_g_source(&priv->linklocal6_timeout_id); - nm_device_activate_schedule_ip_config_timeout(self, AF_INET6); -} - static gboolean -linklocal6_timeout_cb(gpointer user_data) +_dev_ipll6_state_retry_cb(gpointer user_data) { - NMDevice *self = user_data; + NMDevice *self = user_data; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - _LOGD(LOGD_DEVICE, "linklocal6: waiting for link-local addresses failed due to timeout"); - linklocal6_failed(self); - return G_SOURCE_REMOVE; + nm_clear_g_source_inst(&priv->ipll_data_6.v6.retry_source); + _dev_ipll6_start(self); + return G_SOURCE_CONTINUE; } static void -linklocal6_check_complete(NMDevice *self) +_dev_ipll6_set_llstate(NMDevice *self, NML3IPv6LLState llstate, const struct in6_addr *lladdr) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; - const char * method; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gboolean changed = FALSE; + NMDeviceIPState state; + NMDeviceIPState old_state; + + if (!lladdr) + lladdr = &nm_ip_addr_zero.addr6; + + if (priv->ipll_data_6.v6.llstate != llstate + || !IN6_ARE_ADDR_EQUAL(&priv->ipll_data_6.v6.lladdr, lladdr)) { + changed = TRUE; + priv->ipll_data_6.v6.llstate = llstate; + priv->ipll_data_6.v6.lladdr = *lladdr; + } + + nm_assert((priv->ipll_data_6.v6.ipv6ll + && NM_IN_SET(priv->ipll_data_6.v6.llstate, + NM_L3_IPV6LL_STATE_STARTING, + NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, + NM_L3_IPV6LL_STATE_READY, + NM_L3_IPV6LL_STATE_DAD_FAILED)) + || (!priv->ipll_data_6.v6.ipv6ll + && NM_IN_SET(priv->ipll_data_6.v6.llstate, + NM_L3_IPV6LL_STATE_NONE, + NM_L3_IPV6LL_STATE_DEFUNCT))); + + switch (priv->ipll_data_6.v6.llstate) { + case NM_L3_IPV6LL_STATE_NONE: + state = NM_DEVICE_IP_STATE_NONE; + break; + case NM_L3_IPV6LL_STATE_DEFUNCT: + case NM_L3_IPV6LL_STATE_DAD_FAILED: + state = NM_DEVICE_IP_STATE_FAILED; + break; + case NM_L3_IPV6LL_STATE_READY: + state = NM_DEVICE_IP_STATE_READY; + break; + case NM_L3_IPV6LL_STATE_STARTING: + case NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS: + state = NM_DEVICE_IP_STATE_PENDING; + break; + default: + state = nm_assert_unreachable_val(NM_DEVICE_IP_STATE_FAILED); + break; + } - if (!priv->linklocal6_timeout_id) { - /* we are not waiting for linklocal to complete. Nothing to do. */ - return; + old_state = priv->ipll_data_6.state; + if (priv->ipll_data_6.state != state) { + priv->ipll_data_6.state = state; + changed = TRUE; } - if (!priv->ext_ip6_config_captured - || !nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) { - /* we don't have a non-tentative link local address yet. Wait longer. */ - return; + if (priv->ipll_data_6.v6.llstate != NM_L3_IPV6LL_STATE_DEFUNCT) + nm_clear_g_source_inst(&priv->ipll_data_6.v6.retry_source); + else if (!priv->ipll_data_6.v6.retry_source) { + /* we schedule a timer to try to recover from this... Possibly some higher layer + * will however fail the activation... */ + priv->ipll_data_6.v6.retry_source = + nm_g_timeout_add_source(10000, _dev_ipll6_state_retry_cb, self); } - nm_clear_g_source(&priv->linklocal6_timeout_id); + if (changed) { + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - connection = nm_device_get_applied_connection(self); - g_assert(connection); + _LOGT_ipll(AF_INET6, + "set state %s (was %s, llstate=%s, lladdr=%s)", + nm_device_ip_state_to_string(priv->ipll_data_6.state), + nm_device_ip_state_to_string(old_state), + nm_l3_ipv6ll_state_to_string(priv->ipll_data_6.v6.llstate), + nm_ip_addr_is_null(AF_INET6, &priv->ipll_data_6.v6.lladdr) + ? "(none)" + : _nm_utils_inet6_ntop(&priv->ipll_data_6.v6.lladdr, sbuf)); + } - method = nm_device_get_effective_ip_config_method(self, AF_INET6); + if (changed) + _dev_ip_state_check_async(self, AF_INET6); - _LOGD(LOGD_DEVICE, - "linklocal6: waiting for link-local addresses successful, continue with method %s", - method); - - if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP6_CONFIG_METHOD_SHARED)) - addrconf6_start_with_link_ready(self); - else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { - if (!dhcp6_start_with_link_ready(self, connection)) { - /* Time out IPv6 instead of failing the entire activation */ - nm_device_activate_schedule_ip_config_timeout(self, AF_INET6); - } - } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - else - g_return_if_fail(FALSE); + if (priv->ipll_data_6.v6.llstate == NM_L3_IPV6LL_STATE_READY) { + /* if we got an IPv6LL address, we might poke some other methods + * to progress... */ + _dev_ipac6_start_continue(self); + _dev_ipdhcpx_start_continue(self, AF_INET6); + } } static void -check_and_add_ipv6ll_addr(NMDevice *self) +_dev_ipll6_state_change_cb(NML3IPv6LL *ipv6ll, + NML3IPv6LLState llstate, + const struct in6_addr *lladdr, + gpointer user_data) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - struct in6_addr lladdr; - NMConnection * connection; - NMSettingIP6Config *s_ip6 = NULL; - GError * error = NULL; - const char * addr_type; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + _dev_ipll6_set_llstate(user_data, llstate, lladdr); +} - if (!priv->ipv6ll_handle) - return; +static void +_dev_ipll6_start(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMConnection *connection; + NMSettingIP6Config *s_ip6 = NULL; + gboolean assume; + const char *ifname; + NML3IPv6LLState llstate; + const struct in6_addr *lladdr; - if (priv->ext_ip6_config_captured - && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) { - /* Already have an LL address, nothing to do */ + if (priv->ipll_data_6.v6.ipv6ll) return; - } - priv->ipv6ll_has = FALSE; - memset(&priv->ipv6ll_addr, 0, sizeof(priv->ipv6ll_addr)); + if (!priv->l3cfg) { + _LOGD(LOGD_IP6, "linklocal6: no IP link for IPv6"); + goto out_fail; + } - memset(&lladdr, 0, sizeof(lladdr)); - lladdr.s6_addr16[0] = htons(0xfe80); + ifname = nm_device_get_ip_iface(self); + if (!ifname) { + _LOGD(LOGD_IP6, "linklocal6: no interface name for IPv6"); + goto out_fail; + } connection = nm_device_get_applied_connection(self); if (connection) s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection)); + assume = nm_device_sys_iface_state_is_external_or_assume(self); + if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode(s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { NMUtilsStableType stable_type; - const char * stable_id; + const char *stable_id; stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); - if (!nm_utils_ipv6_addr_set_stable_privacy_may_fail(stable_type, - &lladdr, - nm_device_get_iface(self), - stable_id, - priv->linklocal6_dad_counter++, - &error)) { - _LOGW(LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message); - g_clear_error(&error); - linklocal6_failed(self); - return; - } - addr_type = "stable-privacy"; + priv->ipll_data_6.v6.ipv6ll = + nm_l3_ipv6ll_new_stable_privacy(priv->l3cfg, + assume, + stable_type, + ifname, + stable_id, + nm_device_get_route_table(self, AF_INET6), + _dev_ipll6_state_change_cb, + self); } else { NMUtilsIPv6IfaceId iid; - if (priv->linklocal6_timeout_id) { - /* We already started and attempt to add a LL address. For the EUI-64 - * mode we can't pick a new one, we'll just fail. */ - _LOGW(LOGD_IP6, "linklocal6: DAD failed for an EUI-64 address"); - linklocal6_failed(self); - return; - } - - if (!nm_device_get_ip_iface_identifier(self, &iid, TRUE)) { + if (!nm_device_get_ip_iface_identifier(self, &iid, TRUE, NULL)) { _LOGW(LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue"); - return; + goto out_fail; } - nm_utils_ipv6_addr_set_interface_identifier(&lladdr, &iid); - addr_type = "EUI-64"; - } - - _LOGD(LOGD_IP6, - "linklocal6: generated %s IPv6LL address %s", - addr_type, - _nm_utils_inet6_ntop(&lladdr, sbuf)); - priv->ipv6ll_has = TRUE; - priv->ipv6ll_addr = lladdr; - ip_config_merge_and_apply(self, AF_INET6, TRUE); -} - -static gboolean -linklocal6_start(NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - nm_clear_g_source(&priv->linklocal6_timeout_id); - - if (priv->ext_ip6_config_captured - && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured), - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) - return TRUE; - - _LOGD(LOGD_DEVICE, - "linklocal6: starting IPv6 with method '%s', but the device has no link-local addresses " - "configured. Wait.", - nm_device_get_effective_ip_config_method(self, AF_INET6)); + priv->ipll_data_6.v6.ipv6ll = + nm_l3_ipv6ll_new_token(priv->l3cfg, + assume, + &iid, + nm_device_get_route_table(self, AF_INET6), + _dev_ipll6_state_change_cb, + self); + } - check_and_add_ipv6ll_addr(self); + llstate = nm_l3_ipv6ll_get_state(priv->ipll_data_6.v6.ipv6ll, &lladdr); + _dev_ipll6_set_llstate(self, llstate, lladdr); + return; - /* Depending on the network and what the 'dad_transmits' and 'retrans_time_ms' - * sysctl values are, DAD for the IPv6LL address may take quite a while. - * FIXME: use dad/retrans sysctl values if they are higher than a minimum time. - * (rh #1101809) - */ - priv->linklocal6_timeout_id = g_timeout_add_seconds(15, linklocal6_timeout_cb, self); - return FALSE; +out_fail: + _dev_ipll6_set_llstate(self, NM_L3_IPV6LL_STATE_DEFUNCT, NULL); } /*****************************************************************************/ gint64 -nm_device_get_configured_mtu_from_connection_default(NMDevice * self, +nm_device_get_configured_mtu_from_connection_default(NMDevice *self, const char *property_name, guint32 max_mtu) { @@ -10451,13 +10672,13 @@ nm_device_get_configured_mtu_from_connection_default(NMDevice * self, } guint32 -nm_device_get_configured_mtu_from_connection(NMDevice * self, +nm_device_get_configured_mtu_from_connection(NMDevice *self, GType setting_type, NMDeviceMtuSource *out_source) { - const char * global_property_name; + const char *global_property_name; NMConnection *connection; - NMSetting * setting; + NMSetting *setting; gint64 mtu_default; guint32 mtu = 0; guint32 max_mtu = G_MAXUINT32; @@ -10512,17 +10733,17 @@ nm_device_get_configured_mtu_from_connection(NMDevice * self, } guint32 -nm_device_get_configured_mtu_for_wired(NMDevice * self, +nm_device_get_configured_mtu_for_wired(NMDevice *self, NMDeviceMtuSource *out_source, - gboolean * out_force) + gboolean *out_force) { return nm_device_get_configured_mtu_from_connection(self, NM_TYPE_SETTING_WIRED, out_source); } guint32 -nm_device_get_configured_mtu_wired_parent(NMDevice * self, +nm_device_get_configured_mtu_wired_parent(NMDevice *self, NMDeviceMtuSource *out_source, - gboolean * out_force) + gboolean *out_force) { guint32 mtu = 0; guint32 parent_mtu = 0; @@ -10595,13 +10816,16 @@ set_platform_mtu(NMDevice *self, guint32 mtu) } static void -_commit_mtu(NMDevice *self, const NMIP4Config *config) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE; - guint32 ip6_mtu, ip6_mtu_orig; - guint32 mtu_desired, mtu_desired_orig; - guint32 mtu_plat; +_commit_mtu(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE; + const NML3ConfigData *l3cd; + guint32 ip6_mtu_orig; + guint32 ip6_mtu; + guint32 mtu_desired_orig; + guint32 mtu_desired; + guint32 mtu_plat; struct { gboolean initialized; guint32 value; @@ -10609,7 +10833,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) 0, }; int ifindex; - char sbuf[64], sbuf1[64], sbuf2[64]; + char sbuf[64]; + char sbuf1[64]; + char sbuf2[64]; gboolean success = TRUE; ifindex = nm_device_get_ip_ifindex(self); @@ -10623,8 +10849,11 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) return; } + l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, FALSE); + { - guint32 mtu = 0; + guint32 mtu = 0; + guint32 mtu2; gboolean force = FALSE; /* We take the MTU from various sources: (in order of increasing @@ -10651,9 +10880,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config) if (NM_DEVICE_GET_CLASS(self)->get_configured_mtu) mtu = NM_DEVICE_GET_CLASS(self)->get_configured_mtu(self, &source, &force); - if (config && !force && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG - && nm_ip4_config_get_mtu(config)) { - mtu = nm_ip4_config_get_mtu(config); + if (l3cd && !force && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG + && (mtu2 = nm_l3_config_data_get_mtu(l3cd)) > 0) { + mtu = mtu2; source = NM_DEVICE_MTU_SOURCE_IP_CONFIG; } @@ -10842,251 +11071,212 @@ nm_device_commit_mtu(NMDevice *self) state = nm_device_get_state(self); if (state >= NM_DEVICE_STATE_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) { _LOGT(LOGD_DEVICE, "mtu: commit-mtu..."); - _commit_mtu(self, NM_DEVICE_GET_PRIVATE(self)->ip_config_4); + _commit_mtu(self); } else _LOGT(LOGD_DEVICE, "mtu: commit-mtu... skip due to state %s", nm_device_state_to_string(state)); } +/*****************************************************************************/ + static void -ndisc_config_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, NMDevice *self) +_dev_ipac6_ndisc_set_router_config(NMDevice *self) { - NMNDiscConfigMap changed = changed_int; - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - int ifindex; - guint i; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const NML3ConfigData *l3cd; - g_return_if_fail(priv->act_request.obj); + if (!priv->ipac6_data.ndisc) + return; - ifindex = nm_device_get_ip_ifindex(self); + if (nm_ndisc_get_node_type(priv->ipac6_data.ndisc) != NM_NDISC_NODE_TYPE_ROUTER) + return; - if (ifindex <= 0 - || (applied_config_get_current(&priv->ac_ip6_config) - && ifindex - != nm_ip_config_get_ifindex(applied_config_get_current(&priv->ac_ip6_config)))) - applied_config_clear(&priv->ac_ip6_config); + /* FIXME(l3cfg): this doesn't seem right. What is the meaning of the l3cd at this + * point? Also, when do we need to reset the config (and call this function again?). */ + l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, FALSE); + if (l3cd) + nm_ndisc_set_config(priv->ipac6_data.ndisc, l3cd); +} - if (ifindex <= 0) - return; +static void +_dev_ipac6_set_state(NMDevice *self, NMDeviceIPState state) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (!applied_config_get_current(&priv->ac_ip6_config)) - applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6); - - if (changed & NM_NDISC_CONFIG_ADDRESSES) { - guint32 ifa_flags; - - /* Check, whether kernel is recent enough to help user space handling RA. - * If it's not supported, we have no ipv6-privacy and must add autoconf - * addresses as /128. The reason for the /128 is to prevent the kernel - * from adding a prefix route for this address. */ - ifa_flags = IFA_F_NOPREFIXROUTE; - if (NM_IN_SET(priv->ndisc_use_tempaddr, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)) - ifa_flags |= IFA_F_MANAGETEMPADDR; - - nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.orig, - rdata->addresses, - rdata->addresses_n, - 64, - ifa_flags); - if (priv->ac_ip6_config.current) { - nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.current, - rdata->addresses, - rdata->addresses_n, - 64, - ifa_flags); - } + if (priv->ipac6_data.state != state) { + _LOGD_ipac6("set state: %s (was %s)", + nm_device_ip_state_to_string(state), + nm_device_ip_state_to_string(priv->ipac6_data.state)); + priv->ipac6_data.state = state; } +} - if (NM_FLAGS_ANY(changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) { - nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.orig, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6)); - if (priv->ac_ip6_config.current) { - nm_ip6_config_reset_routes_ndisc((NMIP6Config *) priv->ac_ip6_config.current, - rdata->gateways, - rdata->gateways_n, - rdata->routes, - rdata->routes_n, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6)); +static void +_dev_ipac6_ndisc_config_changed(NMNDisc *ndisc, + const NMNDiscData *rdata, + guint changed_i, + const NML3ConfigData *l3cd, + NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gboolean ready = TRUE; + NMDedupMultiIter iter; + const NMPObject *obj; + + _dev_ipac6_grace_period_start(self, 0, TRUE); + + _dev_l3_register_l3cds_set_one_full(self, + L3_CONFIG_DATA_TYPE_AC_6, + l3cd, + NM_L3CFG_CONFIG_FLAGS_FORCE_ONCE, + FALSE); + + nm_clear_l3cd(&priv->ipac6_data.l3cd); + + /* wait that addresses are committed to platform and + * become non-tentative before declaring AC6 is ready.*/ + nm_l3_config_data_iter_obj_for_each (&iter, l3cd, &obj, NMP_OBJECT_TYPE_IP6_ADDRESS) { + const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(obj); + const NMPlatformIP6Address *plat_addr; + + plat_addr = nm_platform_ip6_address_get(nm_device_get_platform(self), + nm_device_get_ip_ifindex(self), + &addr->address); + if (!plat_addr || (plat_addr->n_ifa_flags & IFA_F_TENTATIVE)) { + ready = FALSE; + break; } } - if (changed & NM_NDISC_CONFIG_DNS_SERVERS) { - /* Rebuild DNS server list from neighbor discovery cache. */ - applied_config_reset_nameservers(&priv->ac_ip6_config); - - for (i = 0; i < rdata->dns_servers_n; i++) - applied_config_add_nameserver(&priv->ac_ip6_config, - (const NMIPAddr *) &rdata->dns_servers[i].address); + if (ready) { + _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_READY); + } else { + priv->ipac6_data.l3cd = nm_l3_config_data_ref(l3cd); } - if (changed & NM_NDISC_CONFIG_DNS_DOMAINS) { - /* Rebuild domain list from neighbor discovery cache. */ - applied_config_reset_searches(&priv->ac_ip6_config); - - for (i = 0; i < rdata->dns_domains_n; i++) - applied_config_add_search(&priv->ac_ip6_config, rdata->dns_domains[i].domain); - } + _dev_ipdhcp6_set_dhcp_level(self, rdata->dhcp_level); - if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) { - dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, TRUE); + _dev_l3_cfg_commit(self, FALSE); - priv->dhcp6.mode = rdata->dhcp_level; - if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE) { - _LOGD(LOGD_DEVICE | LOGD_DHCP6, - "Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6" - " as requested by IPv6 router..."); - if (!dhcp6_start(self, FALSE)) { - if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) { - nm_device_state_changed(self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_DHCP_START_FAILED); - return; - } - } - } - } + _dev_ip_state_check_async(self, AF_INET6); +} - if (changed & NM_NDISC_CONFIG_HOP_LIMIT) - nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(nm_device_get_platform(self), - nm_device_get_ip_iface(self), - rdata->hop_limit); +static void +_dev_ipac6_handle_timeout(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) { - nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(nm_device_get_platform(self), - nm_device_get_ip_iface(self), - rdata->reachable_time_ms); - } + _LOGD_ipac6("timeout for autoconf (IPv6 router advertisement) reached"); - if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) { - nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(nm_device_get_platform(self), - nm_device_get_ip_iface(self), - rdata->retrans_timer_ms); - } + nm_clear_g_source_inst(&priv->ipac6_data.ndisc_grace_source); - if (changed & NM_NDISC_CONFIG_MTU) { - if (priv->ip6_mtu != rdata->mtu) { - _LOGD(LOGD_DEVICE, "mtu: set IPv6 MTU to %u", (guint) rdata->mtu); - priv->ip6_mtu = rdata->mtu; - } - } + _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_FAILED); - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); + _dev_ip_state_check_async(self, AF_INET6); } static void -ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self) +_dev_ipac6_ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self) +{ + _dev_ipac6_handle_timeout(self); +} + +static gboolean +_dev_ipac6_grace_period_expired(gpointer user_data) +{ + _dev_ipac6_handle_timeout(user_data); + return G_SOURCE_REMOVE; +} + +static gboolean +_dev_ipac6_grace_period_start(NMDevice *self, guint32 timeout_sec, gboolean force_restart) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gboolean stopped; - /* We don't want to stop listening for router advertisements completely, - * but instead let device activation continue activating. If an RA - * shows up later, we'll use it as long as the device is not disconnected. + /* In any other case (expired lease, assumed connection, etc.), + * wait for some time before failing the IP method. */ - - _LOGD(LOGD_IP6, "timed out waiting for IPv6 router advertisement"); - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) { - /* If RA is our only source of addressing information and we don't - * ever receive one, then time out IPv6. But if there is other - * IPv6 configuration, like manual IPv6 addresses or external IPv6 - * config, consider that sufficient for IPv6 success. - * - * FIXME: it doesn't seem correct to determine this based on which - * addresses we find inside priv->ip_config_6. - */ - if (priv->ip_config_6 - && nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ip_config_6), - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)) - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - else - nm_device_activate_schedule_ip_config_timeout(self, AF_INET6); + if (!force_restart && priv->ipac6_data.ndisc_grace_source) { + /* already pending. */ + return FALSE; } -} -static void -addrconf6_start_with_link_ready(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMUtilsIPv6IfaceId iid; + /* Start a grace period equal to the RA timeout multiplied + * by a constant factor. */ - g_assert(priv->ndisc); + stopped = nm_clear_g_source_inst(&priv->ipac6_data.ndisc_grace_source); - if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) { - _LOGD(LOGD_IP6, "addrconf6: using the device EUI-64 identifier"); - nm_ndisc_set_iid(priv->ndisc, iid); - } else { - /* Don't abort the addrconf at this point -- if ndisc needs the iid - * it will notice this itself. */ - _LOGI(LOGD_IP6, "addrconf6: no interface identifier; IPv6 address creation may fail"); + if (timeout_sec == 0) { + if (stopped) + _LOGD_ipac6("grace period stopped"); + return FALSE; } - /* Apply any manual configuration before starting RA */ - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "failed to apply manual IPv6 configuration"); + nm_assert(timeout_sec <= G_MAXINT32); - if (nm_ndisc_get_node_type(priv->ndisc) == NM_NDISC_NODE_TYPE_ROUTER) { - nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1"); - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - priv->needs_ip6_subnet = TRUE; - g_signal_emit(self, signals[IP6_SUBNET_NEEDED], 0); - } + if (timeout_sec >= G_MAXUINT / (GRACE_PERIOD_MULTIPLIER * 1000u)) + timeout_sec = NM_RA_TIMEOUT_INFINITY; - priv->ndisc_changed_id = g_signal_connect(priv->ndisc, - NM_NDISC_CONFIG_RECEIVED, - G_CALLBACK(ndisc_config_changed), - self); - priv->ndisc_timeout_id = g_signal_connect(priv->ndisc, - NM_NDISC_RA_TIMEOUT_SIGNAL, - G_CALLBACK(ndisc_ra_timeout), - self); + if (timeout_sec == NM_RA_TIMEOUT_INFINITY) { + _LOGD_ipac6("grace period starts with infinity timeout"); + priv->ipac6_data.ndisc_grace_source = g_source_ref(nm_g_source_sentinel_get(0)); + } else { + _LOGD_ipac6("grace period starts with %u seconds", timeout_sec); + priv->ipac6_data.ndisc_grace_source = + nm_g_timeout_add_source(timeout_sec * (GRACE_PERIOD_MULTIPLIER * 1000u), + _dev_ipac6_grace_period_expired, + self); + } - ndisc_set_router_config(priv->ndisc, self); - nm_ndisc_start(priv->ndisc); - priv->ndisc_started = TRUE; - return; + return TRUE; } -static gboolean -addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) +static void +_dev_ipac6_start(NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; - NMSettingIP6Config *s_ip6 = NULL; - GError * error = NULL; - NMUtilsStableType stable_type; - const char * stable_id; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMConnection *connection; + NMSettingIP6Config *s_ip = NULL; NMNDiscNodeType node_type; + NMUtilsStableType stable_type; + const char *stable_id; int max_addresses; int router_solicitations; int router_solicitation_interval; guint32 ra_timeout; guint32 default_ra_timeout; + NMUtilsIPv6IfaceId iid; + gboolean is_token; + + if (priv->ipac6_data.state == NM_DEVICE_IP_STATE_NONE) { + if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) { + _LOGI_ipac6("addrconf6: kernel does not support IPv6"); + _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_FAILED); + _dev_ip_state_check_async(self, AF_INET6); + return; + } - if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) { - _LOGI(LOGD_IP6, "addrconf6: kernel does not support IPv6"); - return FALSE; + _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_PENDING); } - connection = nm_device_get_applied_connection(self); - g_assert(connection); + if (NM_IN_SET(priv->ipll_data_6.state, NM_DEVICE_IP_STATE_NONE, NM_DEVICE_IP_STATE_PENDING)) { + _dev_ipac6_grace_period_start(self, 30, TRUE); + _dev_ipll6_start(self); + return; + } - nm_assert(!applied_config_get_current(&priv->ac_ip6_config)); - applied_config_clear(&priv->ac_ip6_config); + if (priv->ipac6_data.ndisc) { + /* we already started. Nothing to do. */ + return; + } - nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref); - nm_clear_g_source(&priv->rt6_temporary_not_available_id); + connection = nm_device_get_applied_connection(self); + if (connection) + s_ip = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection)); - s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection)); - g_assert(s_ip6); + g_return_if_fail(s_ip); if (nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET6), NM_SETTING_IP6_CONFIG_METHOD_SHARED)) @@ -11109,60 +11299,102 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) ra_timeout = default_ra_timeout; } - stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); - priv->ndisc = nm_lndp_ndisc_new(nm_device_get_platform(self), - nm_device_get_ip_ifindex(self), - nm_device_get_ip_iface(self), - stable_type, - stable_id, - nm_setting_ip6_config_get_addr_gen_mode(s_ip6), - node_type, - max_addresses, - router_solicitations, - router_solicitation_interval, - ra_timeout, - &error); - if (!priv->ndisc) { - _LOGE(LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message); - g_error_free(error); - return FALSE; + stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); + + { + const NMNDiscConfig config = { + .l3cfg = nm_device_get_l3cfg(self), + .ifname = nm_device_get_ip_iface(self), + .stable_type = stable_type, + .network_id = stable_id, + .addr_gen_mode = nm_setting_ip6_config_get_addr_gen_mode(s_ip), + .node_type = node_type, + .max_addresses = max_addresses, + .router_solicitations = router_solicitations, + .router_solicitation_interval = router_solicitation_interval, + .ra_timeout = ra_timeout, + .ip6_privacy = _prop_get_ipv6_ip6_privacy(self), + }; + + priv->ipac6_data.ndisc = nm_lndp_ndisc_new(&config); + + priv->ipac6_data.ndisc_changed_id = + g_signal_connect(priv->ipac6_data.ndisc, + NM_NDISC_CONFIG_RECEIVED, + G_CALLBACK(_dev_ipac6_ndisc_config_changed), + self); + priv->ipac6_data.ndisc_timeout_id = + g_signal_connect(priv->ipac6_data.ndisc, + NM_NDISC_RA_TIMEOUT_SIGNAL, + G_CALLBACK(_dev_ipac6_ndisc_ra_timeout), + self); } - priv->ndisc_use_tempaddr = use_tempaddr; + if (nm_device_get_ip_iface_identifier(self, &iid, FALSE, &is_token)) { + _LOGD_ipac6("using the device EUI-64 identifier"); + nm_ndisc_set_iid(priv->ipac6_data.ndisc, iid, is_token); + } else { + /* Don't abort the addrconf at this point -- if ndisc needs the iid + * it will notice this itself. */ + _LOGD_ipac6("no interface identifier; IPv6 address creation may fail"); + } - /* ensure link local is ready... */ - if (!linklocal6_start(self)) { - /* wait for the LL address to show up */ - return TRUE; + if (nm_ndisc_get_node_type(priv->ipac6_data.ndisc) == NM_NDISC_NODE_TYPE_ROUTER) { + nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1"); + priv->needs_ip6_subnet = TRUE; + g_signal_emit(self, signals[IP6_SUBNET_NEEDED], 0); } - /* already have the LL address; kick off neighbor discovery */ - addrconf6_start_with_link_ready(self); - return TRUE; + _dev_ipac6_ndisc_set_router_config(self); + + if (node_type == NM_NDISC_NODE_TYPE_ROUTER) + _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_READY); + else + _dev_ipac6_grace_period_start(self, ra_timeout, TRUE); + + nm_ndisc_start(priv->ipac6_data.ndisc); +} + +void +nm_device_ip_method_autoconf6_start(NMDevice *self) +{ + _dev_ipac6_start(self); } static void -addrconf6_cleanup(NMDevice *self) +_dev_ipac6_start_continue(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - priv->ndisc_started = FALSE; - nm_clear_g_signal_handler(priv->ndisc, &priv->ndisc_changed_id); - nm_clear_g_signal_handler(priv->ndisc, &priv->ndisc_timeout_id); + if (priv->ipac6_data.state != NM_DEVICE_IP_STATE_NONE) + _dev_ipac6_start(self); +} + +static void +_dev_ipac6_cleanup(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - applied_config_clear(&priv->ac_ip6_config); - nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref); - nm_clear_g_source(&priv->rt6_temporary_not_available_id); - if (priv->ndisc) { - nm_ndisc_stop(priv->ndisc); - g_clear_object(&priv->ndisc); + nm_clear_g_source_inst(&priv->ipac6_data.ndisc_grace_source); + nm_clear_l3cd(&priv->ipac6_data.l3cd); + + nm_clear_g_signal_handler(priv->ipac6_data.ndisc, &priv->ipac6_data.ndisc_changed_id); + nm_clear_g_signal_handler(priv->ipac6_data.ndisc, &priv->ipac6_data.ndisc_timeout_id); + + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, NULL, FALSE); + + if (priv->ipac6_data.ndisc) { + nm_ndisc_stop(priv->ipac6_data.ndisc); + g_clear_object(&priv->ipac6_data.ndisc); } + + _dev_ipac6_set_state(self, NM_DEVICE_IP_STATE_NONE); } /*****************************************************************************/ static void -save_ip6_properties(NMDevice *self) +_dev_sysctl_save_ip6_properties(NMDevice *self) { static const char *const ip6_properties_to_save[] = { "accept_ra", @@ -11172,9 +11404,9 @@ save_ip6_properties(NMDevice *self) "use_tempaddr", }; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMPlatform * platform = nm_device_get_platform(self); - const char * ifname; - char * value; + NMPlatform *platform = nm_device_get_platform(self); + const char *ifname; + char *value; int i; g_hash_table_remove_all(priv->ip6_saved_properties); @@ -11195,61 +11427,90 @@ save_ip6_properties(NMDevice *self) } static void -restore_ip6_properties(NMDevice *self) +_dev_sysctl_restore_ip6_properties(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); GHashTableIter iter; - gpointer key, value; + gpointer key; + gpointer value; g_hash_table_iter_init(&iter, priv->ip6_saved_properties); - while (g_hash_table_iter_next(&iter, &key, &value)) { - /* Don't touch "disable_ipv6" if we're doing userland IPv6LL */ - if (priv->ipv6ll_handle && nm_streq(key, "disable_ipv6")) - continue; + while (g_hash_table_iter_next(&iter, &key, &value)) nm_device_sysctl_ip_conf_set(self, AF_INET6, key, value); - } } static void -set_disable_ipv6(NMDevice *self, const char *value) +_dev_sysctl_set_disable_ipv6(NMDevice *self, gboolean do_disable) { - /* We only touch disable_ipv6 when NM is not managing the IPv6LL address */ - if (!NM_DEVICE_GET_PRIVATE(self)->ipv6ll_handle) - nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", value); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + /* If we previously set addrgenmode=none, we are managing + * IPv6 in user space and we should not disable it. */ + if (do_disable && priv->addrgenmode6_data.previous_mode_has + && priv->addrgenmode6_data.previous_mode_val == NM_IN6_ADDR_GEN_MODE_NONE) + return; + + nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", do_disable ? "1" : "0"); } +/*****************************************************************************/ + static void -set_nm_ipv6ll(NMDevice *self, gboolean enable) +_dev_addrgenmode6_set(NMDevice *self, guint8 addr_gen_mode) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - int ifindex = nm_device_get_ip_ifindex(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int ifindex = nm_device_get_ip_ifindex(self); + const NMPlatformLink *plink; + int r; + int cur_addr_gen_mode; + char sbuf[100]; - priv->ipv6ll_handle = enable; - if (ifindex > 0) { - int r; + if (ifindex <= 0) + return; + + plink = nm_platform_link_get(nm_device_get_platform(self), ifindex); + if (!plink) + return; + + cur_addr_gen_mode = _nm_platform_link_get_inet6_addr_gen_mode(plink); + nm_assert(cur_addr_gen_mode >= 0 && cur_addr_gen_mode <= 255); - _LOGD(LOGD_IP6, "will %s userland IPv6LL", enable ? "enable" : "disable"); + if (!priv->addrgenmode6_data.previous_mode_has) { + priv->addrgenmode6_data.previous_mode_has = TRUE; + priv->addrgenmode6_data.previous_mode_val = cur_addr_gen_mode; + nm_assert(priv->addrgenmode6_data.previous_mode_val == cur_addr_gen_mode); + } + + _LOGD_ip(AF_INET6, + "addrgenmode6: set %s%s", + nm_platform_link_inet6_addrgenmode2str(addr_gen_mode, sbuf, sizeof(sbuf)), + (cur_addr_gen_mode == addr_gen_mode) ? " (already set)" : ""); + + if (cur_addr_gen_mode != addr_gen_mode) { r = nm_platform_link_set_inet6_addr_gen_mode(nm_device_get_platform(self), ifindex, - enable ? NM_IN6_ADDR_GEN_MODE_NONE - : NM_IN6_ADDR_GEN_MODE_EUI64); + addr_gen_mode); if (r < 0) { - _NMLOG(NM_IN_SET(r, -NME_PL_NOT_FOUND, -NME_PL_OPNOTSUPP) ? LOGL_DEBUG : LOGL_WARN, - LOGD_IP6, - "failed to %s userspace IPv6LL address handling (%s)", - enable ? "enable" : "disable", - nm_strerror(r)); + _NMLOG_ip(NM_IN_SET(r, -NME_PL_NOT_FOUND, -NME_PL_OPNOTSUPP) ? LOGL_DEBUG : LOGL_WARN, + AF_INET6, + "addrgenmode6: failed to set %s: (%s)", + nm_platform_link_inet6_addrgenmode2str(addr_gen_mode, sbuf, sizeof(sbuf)), + nm_strerror(r)); + } else { + priv->addrgenmode6_data.previous_mode_val = addr_gen_mode; } + } - if (enable) { - gs_free char *value = NULL; - - /* Bounce IPv6 to ensure the kernel stops IPv6LL address generation */ - value = nm_device_sysctl_ip_conf_get(self, AF_INET6, "disable_ipv6"); - if (nm_streq0(value, "0")) - nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1"); + if (addr_gen_mode == NM_IN6_ADDR_GEN_MODE_NONE) { + gs_free char *value = NULL; - /* Ensure IPv6 is enabled */ + /* Bounce IPv6 to ensure the kernel stops IPv6LL address and temporary + * address generation */ + _LOGD_ip(AF_INET6, + "addrgenmode6: toggle disable_ipv6 sysctl after disabling addr-gen-mode"); + value = nm_device_sysctl_ip_conf_get(self, AF_INET6, "disable_ipv6"); + if (nm_streq0(value, "0")) { + nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1"); nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "0"); } } @@ -11275,30 +11536,41 @@ ip_requires_slaves(NMDevice *self, int addr_family) NM_SETTING_IP6_CONFIG_METHOD_DHCP); } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * self, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static const char * +get_ip_method_auto(NMDevice *self, int addr_family) +{ + return NM_IS_IPv4(addr_family) ? NM_SETTING_IP4_CONFIG_METHOD_AUTO + : NM_SETTING_IP6_CONFIG_METHOD_AUTO; +} + +static void +activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family, const char *method) { const int IS_IPv4 = NM_IS_IPv4(addr_family); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - const char * method; + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); + NMConnection *connection; + int ip_ifindex; - nm_assert_addr_family(addr_family); + if (nm_device_sys_iface_state_is_external(self)) + goto out; connection = nm_device_get_applied_connection(self); + g_return_if_fail(connection); - g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + ip_ifindex = nm_device_get_ip_ifindex(self); if (connection_ip_method_requires_carrier(connection, addr_family, NULL) && nm_device_is_master(self) && !priv->carrier) { - _LOGI(LOGD_IP | LOGD_DEVICE, - "IPv%c config waiting until carrier is on", - nm_utils_addr_family_to_char(addr_family)); - return NM_ACT_STAGE_RETURN_IP_WAIT; + if (!priv->ip_data_x[IS_IPv4].wait_for_carrier) { + _LOGT_ip(addr_family, "waiting until carrier is on"); + priv->ip_data_x[IS_IPv4].wait_for_carrier = TRUE; + } + goto out; + } + if (priv->ip_data_x[IS_IPv4].wait_for_carrier) { + _LOGT_ip(addr_family, "waiting until carrier completed"); + priv->ip_data_x[IS_IPv4].wait_for_carrier = FALSE; } if (nm_device_is_master(self) && ip_requires_slaves(self, addr_family)) { @@ -11306,94 +11578,45 @@ act_stage3_ip_config_start(NMDevice * self, * a successful IP configuration attempt, then postpone IP addressing. */ if (!have_any_ready_slaves(self)) { - _LOGI(LOGD_DEVICE | LOGD_IP, - "IPv%c config waiting until slaves are ready", - nm_utils_addr_family_to_char(addr_family)); - return NM_ACT_STAGE_RETURN_IP_WAIT; + if (!priv->ip_data_x[IS_IPv4].wait_for_ports) { + _LOGT_ip(addr_family, "waiting for ports"); + priv->ip_data_x[IS_IPv4].wait_for_ports = TRUE; + } + goto out; } } + if (priv->ip_data_x[IS_IPv4].wait_for_ports) { + _LOGT_ip(addr_family, "waiting until ports completed"); + priv->ip_data_x[IS_IPv4].wait_for_ports = FALSE; + } - if (!IS_IPv4) - priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE; - - method = nm_device_get_effective_ip_config_method(self, addr_family); - - _LOGD(LOGD_IP | LOGD_DEVICE, - "IPv%c config method is %s", - nm_utils_addr_family_to_char(addr_family), - method); + if (klass->ready_for_ip_config && !klass->ready_for_ip_config(self)) + goto out_devip; if (IS_IPv4) { - if (NM_IN_STRSET(method, - NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { - NMSettingIPConfig *s_ip4; - NMIP4Config ** configs, *config; - guint num_addresses; - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_return_val_if_fail(s_ip4, NM_ACT_STAGE_RETURN_FAILURE); - num_addresses = nm_setting_ip_config_get_num_addresses(s_ip4); - - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { - ret = dhcp4_start(self); - if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED); - return ret; - } - } else { - g_return_val_if_fail(num_addresses != 0, NM_ACT_STAGE_RETURN_FAILURE); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } - - if (num_addresses) { - config = nm_device_ip4_config_new(self); - nm_ip4_config_merge_setting(config, - nm_connection_get_setting_ip4_config(connection), - NM_SETTING_CONNECTION_MDNS_DEFAULT, - NM_SETTING_CONNECTION_LLMNR_DEFAULT, - NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, - nm_device_get_route_table(self, AF_INET), - nm_device_get_route_metric(self, AF_INET)); - configs = g_new0(NMIP4Config *, 2); - configs[0] = config; - ipv4_dad_start(self, configs, ipv4_manual_method_apply); - } - } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { - ret = ipv4ll_start(self); - if (ret == NM_ACT_STAGE_RETURN_FAILURE) - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED); - } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { - if (out_config) { - *out_config = shared4_new_config(self, connection); - if (*out_config) { - priv->dnsmasq_manager = nm_dnsmasq_manager_new(nm_device_get_ip_iface(self)); - ret = NM_ACT_STAGE_RETURN_SUCCESS; - } else { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - ret = NM_ACT_STAGE_RETURN_FAILURE; - } - } else - g_return_val_if_reached(NM_ACT_STAGE_RETURN_FAILURE); - } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) - ret = NM_ACT_STAGE_RETURN_SUCCESS; - else - _LOGW(LOGD_IP4, "unhandled IPv4 config method '%s'; will fail", method); - - return ret; - } else { - NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN; - const char * ip6_privacy_str = "0"; - NMPlatform * platform; - int ifindex; + if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) + _dev_ipdhcpx_start(self, AF_INET); + else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) + _dev_ipll4_start(self); + else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + _dev_ipshared4_start(self); + else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) + priv->ip_data_x[IS_IPv4].is_disabled = TRUE; + else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { + /* pass */ + } else + nm_assert_not_reached(); + } + if (!IS_IPv4) { if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { - nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1"); - return NM_ACT_STAGE_RETURN_IP_DONE; - } - - if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { - if (!nm_device_sys_iface_state_is_external(self)) { + if (!priv->ip_data_x[IS_IPv4].is_disabled) { + priv->ip_data_x[IS_IPv4].is_disabled = TRUE; + nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1"); + } + } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { + if (!priv->ip_data_x[IS_IPv4].is_ignore) { + priv->ip_data_x[IS_IPv4].is_ignore = TRUE; if (priv->master) { /* If a device only has an IPv6 link-local address, * we don't generate an assumed connection. Therefore, @@ -11403,174 +11626,56 @@ act_stage3_ip_config_start(NMDevice * self, * slave should not depend on the previous state. Flush * addresses and routes on activation. */ - ifindex = nm_device_get_ip_ifindex(self); - platform = nm_device_get_platform(self); - - if (ifindex > 0) { - gs_unref_object NMIP6Config *config = nm_device_ip6_config_new(self); - - nm_platform_ip_route_flush(platform, AF_INET6, ifindex); - nm_platform_ip_address_flush(platform, AF_INET6, ifindex); - nm_device_set_ip_config(self, AF_INET6, (NMIPConfig *) config, FALSE, NULL); + if (ip_ifindex > 0) { + nm_platform_ip_route_flush(nm_device_get_platform(self), + AF_INET6, + ip_ifindex); + nm_platform_ip_address_flush(nm_device_get_platform(self), + AF_INET6, + ip_ifindex); } } else { - gboolean ipv6ll_handle_old = priv->ipv6ll_handle; - /* When activating an IPv6 'ignore' connection we need to revert back * to kernel IPv6LL, but the kernel won't actually assign an address * to the interface until disable_ipv6 is bounced. */ - set_nm_ipv6ll(self, FALSE); - if (ipv6ll_handle_old) - nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1"); - restore_ip6_properties(self); + _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_EUI64); + _dev_sysctl_set_disable_ipv6(self, TRUE); + _dev_sysctl_restore_ip6_properties(self); } } - return NM_ACT_STAGE_RETURN_IP_DONE; - } - - /* Ensure the MTU makes sense. If it was below 1280 the kernel would not - * expose any ipv6 sysctls or allow presence of any addresses on the interface, - * including LL, which * would make it impossible to autoconfigure MTU to a - * correct value. */ - _commit_mtu(self, priv->ip_config_4); - - /* Any method past this point requires an IPv6LL address. Use NM-controlled - * IPv6LL if this is not an assumed connection, since assumed connections - * will already have IPv6 set up. - */ - if (!nm_device_sys_iface_state_is_external_or_assume(self)) - set_nm_ipv6ll(self, TRUE); - - /* Re-enable IPv6 on the interface */ - nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "0"); - set_disable_ipv6(self, "0"); - - /* Synchronize external IPv6 configuration with kernel, since - * linklocal6_start() uses the information there to determine if we can - * proceed with the selected method (SLAAC, DHCP, link-local). - */ - nm_platform_process_events(nm_device_get_platform(self)); - g_clear_object(&priv->ext_ip6_config_captured); - priv->ext_ip6_config_captured = - nm_ip6_config_capture(nm_device_get_multi_index(self), - nm_device_get_platform(self), - nm_device_get_ip_ifindex(self), - NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - - ip6_privacy = _prop_get_ipv6_ip6_privacy(self); - - if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_AUTO, - NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { - if (!addrconf6_start(self, ip6_privacy)) { - /* IPv6 might be disabled; allow IPv4 to proceed */ - ret = NM_ACT_STAGE_RETURN_IP_FAIL; - } else - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) { - ret = - linklocal6_start(self) ? NM_ACT_STAGE_RETURN_SUCCESS : NM_ACT_STAGE_RETURN_POSTPONE; - } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { - priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED; - if (!dhcp6_start(self, TRUE)) { - /* IPv6 might be disabled; allow IPv4 to proceed */ - ret = NM_ACT_STAGE_RETURN_IP_FAIL; + } else { + _dev_ipll6_start(self); + + if (NM_IN_STRSET(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) + _dev_ipac6_start(self); + else if (NM_IN_STRSET(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) + _dev_ipshared6_start(self); + else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { + priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_MANAGED; + _dev_ipdhcpx_start(self, AF_INET6); } else - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) - ret = NM_ACT_STAGE_RETURN_SUCCESS; - else - _LOGW(LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method); - - if (ret != NM_ACT_STAGE_RETURN_FAILURE - && !nm_device_sys_iface_state_is_external_or_assume(self)) { - switch (ip6_privacy) { - case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: - case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: - ip6_privacy_str = "0"; - break; - case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: - ip6_privacy_str = "1"; - break; - case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: - ip6_privacy_str = "2"; - break; - } - nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", ip6_privacy_str); + nm_assert(NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)); } - - return ret; - } -} - -gboolean -nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family) -{ - const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMActStageReturn ret; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - gs_unref_object NMIPConfig *ip_config = NULL; - - g_assert(priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_WAIT); - - if (nm_device_sys_iface_state_is_external(self)) { - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - return TRUE; } - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_CONF); - - ret = NM_DEVICE_GET_CLASS(self)->act_stage3_ip_config_start(self, - addr_family, - (gpointer *) &ip_config, - &failure_reason); - - switch (ret) { - case NM_ACT_STAGE_RETURN_SUCCESS: - if (!IS_IPv4) { - /* Here we get a static IPv6 config, like for Shared where it's - * autogenerated or from modems where it comes from ModemManager. - */ - if (!ip_config) - ip_config = nm_device_ip_config_new(self, addr_family); - nm_assert(!applied_config_get_current(&priv->ac_ip6_config)); - applied_config_init(&priv->ac_ip6_config, ip_config); - ip_config = NULL; - } - nm_device_activate_schedule_ip_config_result(self, addr_family, ip_config); - break; - case NM_ACT_STAGE_RETURN_IP_DONE: - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - break; - case NM_ACT_STAGE_RETURN_FAILURE: - nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason); - return FALSE; - case NM_ACT_STAGE_RETURN_IP_FAIL: - /* Activation not wanted */ - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL); - break; - case NM_ACT_STAGE_RETURN_IP_WAIT: - /* Wait for something to try IP config again */ - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_WAIT); - break; - default: - g_assert(ret == NM_ACT_STAGE_RETURN_POSTPONE); - } +out_devip: + if (klass->act_stage3_ip_config) + klass->act_stage3_ip_config(self, addr_family); - return TRUE; +out: + _dev_ip_state_check_async(self, addr_family); } static void -fw_change_zone_cb(NMFirewalldManager * firewalld_manager, +fw_change_zone_cb(NMFirewalldManager *firewalld_manager, NMFirewalldManagerCallId *call_id, - GError * error, + GError *error, gpointer user_data) { - NMDevice * self = user_data; + NMDevice *self = user_data; NMDevicePrivate *priv; g_return_if_fail(NM_IS_DEVICE(self)); @@ -11588,12 +11693,12 @@ fw_change_zone_cb(NMFirewalldManager * firewalld_manager, switch (priv->fw_state) { case FIREWALL_STATE_WAIT_STAGE_3: priv->fw_state = FIREWALL_STATE_INITIALIZED; - nm_device_activate_schedule_stage3_ip_config_start(self); + nm_device_activate_schedule_stage3_ip_config(self, TRUE); break; case FIREWALL_STATE_WAIT_IP_CONFIG: priv->fw_state = FIREWALL_STATE_INITIALIZED; - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE - || priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) + if (priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY + || priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY) nm_device_start_ip_check(self); break; case FIREWALL_STATE_INITIALIZED: @@ -11606,10 +11711,10 @@ fw_change_zone_cb(NMFirewalldManager * firewalld_manager, static void fw_change_zone(NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * applied_connection; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMConnection *applied_connection; NMSettingConnection *s_con; - const char * zone; + const char *zone; nm_assert(priv->fw_state >= FIREWALL_STATE_INITIALIZED); @@ -11645,24 +11750,51 @@ fw_change_zone(NMDevice *self) self); } -/* - * activate_stage3_ip_config_start - * - * Begin automatic/manual IP configuration - * - */ static void -activate_stage3_ip_config_start(NMDevice *self) +activate_stage3_ip_config(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); int ifindex; + const char *ipv4_method; + const char *ipv6_method; + + /* stage3 is different from stage1+2. + * + * What is true in all cases is that when we start a stage, we call the corresponding + * nm_device_activate_schedule_stage*() function. But usually the stage cannot complete + * right away but needs to wait for some things to happen. So the activate_stage*() function + * returns, and will be later proceeded by calling *the same* stage again. That means, + * activate_stage*() must be re-entrant and be called repeatedly until we can proceed + * to the next stage. Only when the stage is completed, we schedule the next one. + * + * stage3 is different. It does IP configuration and as such (the stage handling itself) + * cannot fail. If a failure happens (for example for DHCP), we remember that (in priv->ipdhcp_data_x) + * and issue _dev_ip_state_check_async(). That one combines the DHCP state to determine the + * overall per-address-family state (priv->ip_data_x). Those states are then combined + * further into priv->combinedip_state, which then leads to nm_device_state_changed() + * (which for example can make the device fully ACTIVATED or FAILED). + * + * The difference between stage1+2 and stage3 is that IP configuration is running continuously + * while the device is active. As such the activate_stage3_ip_config() does not fail directly, + * unlike the other stages which can abort via NM_ACT_STAGE_RETURN_FAILURE. */ g_return_if_fail(priv->act_request.obj); ifindex = nm_device_get_ip_ifindex(self); + if (priv->ip_data_4.do_reapply) { + _LOGD_ip(AF_INET, "reapply..."); + _cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_DECONFIGURE, TRUE); + } + if (priv->ip_data_6.do_reapply) { + _LOGD_ip(AF_INET6, "reapply..."); + _cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_DECONFIGURE, TRUE); + } + /* Add the interface to the specified firewall zone */ - if (priv->fw_state == FIREWALL_STATE_UNMANAGED) { + switch (priv->fw_state) { + case FIREWALL_STATE_UNMANAGED: if (nm_device_sys_iface_state_is_external(self)) { /* fake success */ priv->fw_state = FIREWALL_STATE_INITIALIZED; @@ -11672,143 +11804,182 @@ activate_stage3_ip_config_start(NMDevice *self) return; } /* no ifindex, nothing to do for now */ - } else if (priv->fw_state == FIREWALL_STATE_WAIT_STAGE_3) { + break; + case FIREWALL_STATE_WAIT_STAGE_3: /* a firewall call for stage3 is pending. Return and wait. */ return; + default: + nm_assert(NM_IN_SET((FirewallState) priv->fw_state, + FIREWALL_STATE_INITIALIZED, + FIREWALL_STATE_WAIT_IP_CONFIG)); + break; } - nm_assert(ifindex <= 0 || priv->fw_state == FIREWALL_STATE_INITIALIZED); - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT); - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT); + if (priv->state < NM_DEVICE_STATE_IP_CONFIG) { + _dev_ip_state_req_timeout_schedule(self, AF_INET); + _dev_ip_state_req_timeout_schedule(self, AF_INET6); - _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY); + _active_connection_set_state_flags(self, NM_ACTIVATION_STATE_FLAG_LAYER2_READY); - nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); + nm_device_state_changed(self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); - /* Device should be up before we can do anything with it */ - if (!nm_device_sys_iface_state_is_external(self) - && (ifindex = nm_device_get_ip_ifindex(self)) > 0 - && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex)) - _LOGW(LOGD_DEVICE, - "interface %s not up for IP configuration", - nm_device_get_ip_iface(self)); + /* Device should be up before we can do anything with it */ + if (!nm_device_sys_iface_state_is_external(self) && ifindex > 0 + && !nm_platform_link_is_up(nm_device_get_platform(self), ifindex)) + _LOGW(LOGD_DEVICE, + "interface %s not up for IP configuration", + nm_device_get_ip_iface(self)); + } - if (nm_device_activate_ip4_state_in_wait(self) - && !nm_device_activate_stage3_ip_start(self, AF_INET)) - return; + ipv4_method = nm_device_get_effective_ip_config_method(self, AF_INET); + if (nm_streq(ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + /* "auto" usually means DHCPv4 or autoconf6, but it doesn't have to be. Subclasses + * can overwrite it. For example, you cannot run DHCPv4 on PPP/WireGuard links. */ + ipv4_method = klass->get_ip_method_auto(self, AF_INET); + } - if (nm_device_activate_ip6_state_in_wait(self) - && !nm_device_activate_stage3_ip_start(self, AF_INET6)) - return; + ipv6_method = nm_device_get_effective_ip_config_method(self, AF_INET6); + if (nm_streq(ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { + ipv6_method = klass->get_ip_method_auto(self, AF_INET6); + } + + if (!nm_device_sys_iface_state_is_external(self) + && (!klass->ready_for_ip_config || klass->ready_for_ip_config(self))) { + if (priv->ipmanual_data.state_6 == NM_DEVICE_IP_STATE_NONE + && !NM_IN_STRSET(ipv6_method, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { + /* Ensure the MTU makes sense. If it was below 1280 the kernel would not + * expose any ipv6 sysctls or allow presence of any addresses on the interface, + * including LL, which * would make it impossible to autoconfigure MTU to a + * correct value. */ + _commit_mtu(self); + + /* Any method past this point requires an IPv6LL address. Use NM-controlled + * IPv6LL if this is not an assumed connection, since assumed connections + * will already have IPv6 set up. + */ + if (!nm_device_sys_iface_state_is_external_or_assume(self)) + _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE); - /* Proxy */ - nm_device_set_proxy_config(self, NULL); + /* Re-enable IPv6 on the interface */ + nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "0"); + _dev_sysctl_set_disable_ipv6(self, FALSE); + } + + _dev_ipmanual_start(self); + } - check_ip_state(self, TRUE, TRUE); + activate_stage3_ip_config_for_addr_family(self, AF_INET, ipv4_method); + activate_stage3_ip_config_for_addr_family(self, AF_INET6, ipv6_method); } -/* - * nm_device_activate_schedule_stage3_ip_config_start - * - * Schedule IP configuration start - */ void -nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) +nm_device_activate_schedule_stage3_ip_config(NMDevice *self, gboolean do_sync) { - NMDevicePrivate *priv; - - g_return_if_fail(NM_IS_DEVICE(self)); - - priv = NM_DEVICE_GET_PRIVATE(self); - - g_return_if_fail(priv->act_request.obj); - - activation_source_schedule(self, activate_stage3_ip_config_start, AF_INET); + activation_source_invoke_or_schedule(self, activate_stage3_ip_config, do_sync); } -static NMActStageReturn -act_stage4_ip_config_timeout(NMDevice * self, - int addr_family, - NMDeviceStateReason *out_failure_reason) +/*****************************************************************************/ + +static void +_dev_ipsharedx_set_state(NMDevice *self, int addr_family, NMDeviceIPState state) { - nm_assert_addr_family(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - if (!get_ip_config_may_fail(self, addr_family)) { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return NM_ACT_STAGE_RETURN_FAILURE; + if (priv->ipshared_data_x[IS_IPv4].state != state) { + _LOGD_ipshared(addr_family, + "set state %s (was %s)", + nm_device_ip_state_to_string(state), + nm_device_ip_state_to_string(priv->ipshared_data_x[IS_IPv4].state)); + priv->ipshared_data_x[IS_IPv4].state = state; } - - return NM_ACT_STAGE_RETURN_SUCCESS; } static void -activate_stage4_ip_config_timeout_x(NMDevice *self, int addr_family) +_dev_ipsharedx_cleanup(NMDevice *self, int addr_family) { - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - NMActStageReturn ret; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - ret = - NM_DEVICE_GET_CLASS(self)->act_stage4_ip_config_timeout(self, addr_family, &failure_reason); + if (IS_IPv4) { + if (priv->ipshared_data_4.v4.dnsmasq_manager) { + nm_clear_g_signal_handler(priv->ipshared_data_4.v4.dnsmasq_manager, + &priv->ipshared_data_4.v4.dnsmasq_state_id); + nm_dnsmasq_manager_stop(priv->ipshared_data_4.v4.dnsmasq_manager); + g_clear_object(&priv->ipshared_data_4.v4.dnsmasq_manager); + } - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - return; + if (priv->ipshared_data_4.v4.firewall_config) { + nm_firewall_config_apply(priv->ipshared_data_4.v4.firewall_config, FALSE); + nm_clear_pointer(&priv->ipshared_data_4.v4.firewall_config, nm_firewall_config_free); + } - if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason); - return; + nm_clear_pointer(&priv->ipshared_data_4.v4.shared_ip_handle, nm_netns_shared_ip_release); + nm_clear_l3cd(&priv->ipshared_data_4.v4.l3cd); + + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, NULL, FALSE); } - g_assert(ret == NM_ACT_STAGE_RETURN_SUCCESS); - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL); - check_ip_state(self, FALSE, TRUE); + _dev_ipsharedx_set_state(self, addr_family, NM_DEVICE_IP_STATE_NONE); } -static void -activate_stage4_ip_config_timeout_4(NMDevice *self) -{ - activate_stage4_ip_config_timeout_x(self, AF_INET); -} +/*****************************************************************************/ -static void -activate_stage4_ip_config_timeout_6(NMDevice *self) +static const NML3ConfigData * +_dev_ipshared4_new_l3cd(NMDevice *self, NMConnection *connection, NMPlatformIP4Address *out_addr4) { - activate_stage4_ip_config_timeout_x(self, AF_INET6); -} + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + NMSettingIPConfig *s_ip4; + NMPlatformIP4Address address = { + .addr_source = NM_IP_CONFIG_SOURCE_SHARED, + }; -#define activate_stage4_ip_config_timeout_x_fcn(addr_family) \ - (NM_IS_IPv4(addr_family) ? activate_stage4_ip_config_timeout_4 \ - : activate_stage4_ip_config_timeout_6) + g_return_val_if_fail(self, NULL); + g_return_val_if_fail(connection, NULL); -void -nm_device_activate_schedule_ip_config_timeout(NMDevice *self, int addr_family) -{ - NMDevicePrivate *priv; + s_ip4 = nm_connection_get_setting_ip4_config(connection); + if (s_ip4 && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) { + /* Use the first user-supplied address */ + NMIPAddress *user = nm_setting_ip_config_get_address(s_ip4, 0); + in_addr_t a; - g_return_if_fail(NM_IS_DEVICE(self)); + nm_ip_address_get_address_binary(user, &a); + nm_platform_ip4_address_set_addr(&address, a, nm_ip_address_get_prefix(user)); + nm_clear_pointer(&priv->ipshared_data_4.v4.shared_ip_handle, nm_netns_shared_ip_release); + } else { + if (!priv->ipshared_data_4.v4.shared_ip_handle) + priv->ipshared_data_4.v4.shared_ip_handle = + nm_netns_shared_ip_reserve(nm_device_get_netns(self)); + nm_platform_ip4_address_set_addr(&address, + priv->ipshared_data_4.v4.shared_ip_handle->addr, + 24); + } - priv = NM_DEVICE_GET_PRIVATE(self); + l3cd = nm_device_create_l3_config_data(self, NM_IP_CONFIG_SOURCE_SHARED); + nm_l3_config_data_add_address_4(l3cd, &address); - g_return_if_fail(priv->act_request.obj); + NM_SET_OUT(out_addr4, address); - activation_source_schedule(self, - activate_stage4_ip_config_timeout_x_fcn(addr_family), - addr_family); + return nm_l3_config_data_seal(g_steal_pointer(&l3cd)); } static gboolean -share_init(NMDevice *self, GError **error) -{ - const char *const modules[] = {"ip_tables", - "iptable_nat", - "nf_nat_ftp", - "nf_nat_irc", - "nf_nat_sip", - "nf_nat_tftp", - "nf_nat_pptp", - "nf_nat_h323"}; - guint i; - int errsv; +_dev_ipshared4_init(NMDevice *self) +{ + static const char *const modules[] = {"ip_tables", + "iptable_nat", + "nf_nat_ftp", + "nf_nat_irc", + "nf_nat_sip", + "nf_nat_tftp", + "nf_nat_pptp", + "nf_nat_h323"}; + int errsv; + guint i; if (nm_platform_sysctl_get_int32(nm_device_get_platform(self), NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"), @@ -11819,15 +11990,7 @@ share_init(NMDevice *self, GError **error) NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"), "1")) { errsv = errno; - _LOGD(LOGD_SHARING, - "share: error enabling IPv4 forwarding: (%d) %s", - errsv, - nm_strerror_native(errsv)); - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "cannot set ipv4/ip_forward: %s", - nm_strerror_native(errsv)); + _LOGW_ipshared(AF_INET, "error enabling IPv4 forwarding: %s", nm_strerror_native(errsv)); return FALSE; } @@ -11840,10 +12003,9 @@ share_init(NMDevice *self, GError **error) NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_dynaddr"), "1")) { errsv = errno; - _LOGD(LOGD_SHARING, - "share: error enabling dynamic addresses: (%d) %s", - errsv, - nm_strerror_native(errsv)); + _LOGD_ipshared(AF_INET, + "share: error enabling dynamic addresses: %s", + nm_strerror_native(errsv)); } for (i = 0; i < G_N_ELEMENTS(modules); i++) @@ -11852,48 +12014,86 @@ share_init(NMDevice *self, GError **error) return TRUE; } -static gboolean -start_sharing(NMDevice *self, NMIP4Config *config, GError **error) +static void +_dev_ipshared4_dnsmasq_state_changed_cb(NMDnsMasqManager *manager, guint status, gpointer user_data) +{ + NMDevice *self = NM_DEVICE(user_data); + + if (status != NM_DNSMASQ_STATUS_DEAD) + return; + + _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_FAILED); + _dev_ip_state_check_async(self, AF_INET); +} + +static void +_dev_ipshared4_start(NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMActRequest * req; - const NMPlatformIP4Address *ip4_addr = NULL; - const char * ip_iface; - GError * local = NULL; - NMConnection * conn; - NMSettingConnection * s_con; - gboolean announce_android_metered; - NMFirewallConfig * firewall_config; + nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; + NMPlatformIP4Address ip4_addr; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const char *ip_iface; + NMConnection *applied; - g_return_val_if_fail(config, FALSE); + if (priv->ipshared_data_4.state != NM_DEVICE_IP_STATE_NONE) + return; + + nm_assert(!priv->ipshared_data_4.v4.firewall_config); + nm_assert(!priv->ipshared_data_4.v4.dnsmasq_manager); + nm_assert(priv->ipshared_data_4.v4.dnsmasq_state_id == 0); ip_iface = nm_device_get_ip_iface(self); - if (!ip_iface) { - g_set_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "device has no ip interface"); - return FALSE; - } + g_return_if_fail(ip_iface); - ip4_addr = nm_ip4_config_get_first_address(config); - if (!ip4_addr || !ip4_addr->address) { - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "could not determine IPv4 address"); - return FALSE; + applied = nm_device_get_applied_connection(self); + g_return_if_fail(applied); + + _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_PENDING); + + l3cd = _dev_ipshared4_new_l3cd(self, applied, &ip4_addr); + if (!l3cd) { + nm_assert_not_reached(); + goto out_fail; } - if (!share_init(self, error)) - return FALSE; + if (!_dev_ipshared4_init(self)) + goto out_fail; + + priv->ipshared_data_4.v4.firewall_config = + nm_firewall_config_new(ip_iface, ip4_addr.address, ip4_addr.plen); + nm_firewall_config_apply(priv->ipshared_data_4.v4.firewall_config, TRUE); + + priv->ipshared_data_4.v4.l3cd = nm_l3_config_data_ref(l3cd); + _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, l3cd, FALSE); - req = nm_device_get_act_request(self); - g_return_val_if_fail(req, FALSE); + /* Wait that the address gets committed before spawning dnsmasq */ + return; +out_fail: + _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_FAILED); + _dev_ip_state_check_async(self, AF_INET); +} - firewall_config = nm_firewall_config_new(ip_iface, ip4_addr->address, ip4_addr->plen); +static void +_dev_ipshared4_spawn_dnsmasq(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const char *ip_iface; + gs_free_error GError *error = NULL; + NMSettingConnection *s_con; + gboolean announce_android_metered; + NMConnection *applied; - nm_act_request_set_shared(req, firewall_config); + nm_assert(priv->ipshared_data_4.v4.firewall_config); + nm_assert(priv->ipshared_data_4.v4.dnsmasq_state_id == 0); + nm_assert(!priv->ipshared_data_4.v4.dnsmasq_manager); + nm_assert(priv->ipshared_data_4.v4.l3cd); - conn = nm_act_request_get_applied_connection(req); - s_con = nm_connection_get_setting_connection(conn); + ip_iface = nm_device_get_ip_iface(self); + g_return_if_fail(ip_iface); + + applied = nm_device_get_applied_connection(self); + g_return_if_fail(applied); + s_con = nm_connection_get_setting_connection(applied); switch (nm_setting_connection_get_metered(s_con)) { case NM_METERED_YES: @@ -11915,353 +12115,54 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error) break; } - if (!nm_dnsmasq_manager_start(priv->dnsmasq_manager, - config, + priv->ipshared_data_4.v4.dnsmasq_manager = nm_dnsmasq_manager_new(ip_iface); + if (!nm_dnsmasq_manager_start(priv->ipshared_data_4.v4.dnsmasq_manager, + priv->ipshared_data_4.v4.l3cd, announce_android_metered, - &local)) { - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "could not start dnsmasq due to %s", - local->message); - g_error_free(local); - nm_act_request_set_shared(req, NULL); - return FALSE; + &error)) { + _LOGW_ipshared(AF_INET, "could not start dnsmasq: %s", error->message); + goto out_fail; } - priv->dnsmasq_state_id = g_signal_connect(priv->dnsmasq_manager, - NM_DNS_MASQ_MANAGER_STATE_CHANGED, - G_CALLBACK(dnsmasq_state_changed_cb), - self); - return TRUE; -} + priv->ipshared_data_4.v4.dnsmasq_state_id = + g_signal_connect(priv->ipshared_data_4.v4.dnsmasq_manager, + NM_DNS_MASQ_MANAGER_STATE_CHANGED, + G_CALLBACK(_dev_ipshared4_dnsmasq_state_changed_cb), + self); -static void -arp_cleanup(NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_READY); + _dev_ip_state_check_async(self, AF_INET); + return; - nm_clear_pointer(&priv->acd.announcing, nm_acd_manager_free); +out_fail: + _dev_ipsharedx_set_state(self, AF_INET, NM_DEVICE_IP_STATE_FAILED); + _dev_ip_state_check_async(self, AF_INET); } -void -nm_device_arp_announce(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; - NMSettingIPConfig *s_ip4; - guint num, i; - const guint8 * hw_addr; - size_t hw_addr_len = 0; - - arp_cleanup(self); - - hw_addr = nm_platform_link_get_address(nm_device_get_platform(self), - nm_device_get_ip_ifindex(self), - &hw_addr_len); - - if (!hw_addr || hw_addr_len != ETH_ALEN) - return; - - /* We only care about manually-configured addresses; DHCP- and autoip-configured - * ones should already have been seen on the network at this point. - */ - connection = nm_device_get_applied_connection(self); - if (!connection) - return; - s_ip4 = nm_connection_get_setting_ip4_config(connection); - if (!s_ip4) - return; - num = nm_setting_ip_config_get_num_addresses(s_ip4); - if (num == 0) - return; - - priv->acd.announcing = - nm_acd_manager_new(nm_device_get_ip_ifindex(self), hw_addr, hw_addr_len, NULL, NULL); - - for (i = 0; i < num; i++) { - NMIPAddress *ip = nm_setting_ip_config_get_address(s_ip4, i); - in_addr_t addr; - - if (inet_pton(AF_INET, nm_ip_address_get_address(ip), &addr) == 1) - nm_acd_manager_add_address(priv->acd.announcing, addr); - else - g_warn_if_reached(); - } - - nm_acd_manager_announce_addresses(priv->acd.announcing); -} +/*****************************************************************************/ static void -activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) +_dev_ipshared6_start(NMDevice *self) { - const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMActRequest * req; - const char * method; - int ip_ifindex; - int errsv; - - req = nm_device_get_act_request(self); - g_assert(req); - - nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[IS_IPv4]); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - /* Interface must be IFF_UP before IP config can be applied */ - ip_ifindex = nm_device_get_ip_ifindex(self); - g_return_if_fail(ip_ifindex); + _dev_ipac6_start(self); - if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex) - && !nm_device_sys_iface_state_is_external(self)) { - nm_platform_link_change_flags(nm_device_get_platform(self), ip_ifindex, IFF_UP, TRUE); - if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)) - _LOGW(LOGD_DEVICE, - "interface %s not up for IP configuration", - nm_device_get_ip_iface(self)); - } - - if (!ip_config_merge_and_apply(self, addr_family, TRUE)) { - _LOGD(LOGD_DEVICE | LOGD_IPX(IS_IPv4), - "Activation: Stage 5 of 5 (IPv%c Commit) failed", - nm_utils_addr_family_to_char(addr_family)); - nm_device_ip_method_failed(self, addr_family, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + if (priv->ipshared_data_6.state != NM_DEVICE_IP_STATE_NONE) return; - } - - if (!IS_IPv4) { - if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE - && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) { - if (applied_config_get_current(&priv->dhcp6.ip6_config)) { - /* If IPv6 wasn't the first IP to complete, and DHCP was used, - * then ensure dispatcher scripts get the DHCP lease information. - */ - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, - self, - NULL, - NULL, - NULL, - NULL); - } else { - /* still waiting for first dhcp6 lease. */ - return; - } - } - } - - /* Start IPv4 sharing/IPv6 forwarding if we need it */ - method = nm_device_get_effective_ip_config_method(self, addr_family); - if (IS_IPv4) { - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { - gs_free_error GError *error = NULL; - - if (!start_sharing(self, priv->ip_config_4, &error)) { - _LOGW(LOGD_SHARING, - "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed: %s", - error->message); - nm_device_ip_method_failed(self, - AF_INET, - NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - return; - } - } - } else { - if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { - if (!nm_platform_sysctl_set( - nm_device_get_platform(self), - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv6/conf/all/forwarding"), - "1")) { - errsv = errno; - _LOGE(LOGD_SHARING, - "share: error enabling IPv6 forwarding: (%d) %s", - errsv, - nm_strerror_native(errsv)); - nm_device_ip_method_failed(self, - AF_INET6, - NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - return; - } - } - } - - if (IS_IPv4) { - if (priv->dhcp_data_4.client) { - gs_free_error GError *error = NULL; - - if (!nm_dhcp_client_accept(priv->dhcp_data_4.client, &error)) { - _LOGW(LOGD_DHCP4, - "Activation: Stage 5 of 5 (IPv4 Commit) error accepting lease: %s", - error->message); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_DHCP_ERROR); - return; - } - } - - /* If IPv4 wasn't the first to complete, and DHCP was used, then ensure - * dispatcher scripts get the DHCP lease information. - */ - if (priv->dhcp_data_4.client && nm_device_activate_ip4_state_in_conf(self) - && (nm_device_get_state(self) > NM_DEVICE_STATE_IP_CONFIG)) { - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, - self, - NULL, - NULL, - NULL, - NULL); - } - } - - if (!IS_IPv4) { - /* Check if we have to wait for DAD */ - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF && !priv->dad6_ip6_config) { - if (!priv->carrier && priv->ignore_carrier && get_ip_config_may_fail(self, AF_INET6)) - _LOGI(LOGD_DEVICE | LOGD_IP6, - "IPv6 DAD: carrier missing and ignored, not delaying activation"); - else - priv->dad6_ip6_config = dad6_get_pending_addresses(self); - - if (priv->dad6_ip6_config) { - _LOGD(LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination"); - } else { - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - } - } - } - - if (IS_IPv4 && priv->carrier) { - /* We send ARP announcements only when the link gets carrier, - * otherwise the announcements would be lost. Furthermore, for - * controllers having carrier implies that there is at least one - * port and therefore the MAC address is the correct one. - */ - nm_device_arp_announce(self); - } - - if (IS_IPv4) { - /* Enter the IP_CHECK state if this is the first method to complete */ - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - } -} - -static void -activate_stage5_ip_config_result_4(NMDevice *self) -{ - activate_stage5_ip_config_result_x(self, AF_INET); -} - -static void -activate_stage5_ip_config_result_6(NMDevice *self) -{ - activate_stage5_ip_config_result_x(self, AF_INET6); -} - -#define activate_stage5_ip_config_result_x_fcn(addr_family) \ - (NM_IS_IPv4(addr_family) ? activate_stage5_ip_config_result_4 \ - : activate_stage5_ip_config_result_6) - -void -nm_device_activate_schedule_ip_config_result(NMDevice *self, int addr_family, NMIPConfig *config) -{ - NMDevicePrivate *priv; - const int IS_IPv4 = NM_IS_IPv4(addr_family); - - g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(!config || (IS_IPv4 && nm_ip_config_get_addr_family(config) == AF_INET)); - - priv = NM_DEVICE_GET_PRIVATE(self); - if (IS_IPv4) { - applied_config_init(&priv->dev_ip_config_4, config); - } else { - /* If IP had previously failed, move it back to NM_DEVICE_IP_STATE_CONF since we - * clearly now have configuration. - */ - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL) - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_CONF); - } - - activation_source_schedule(self, - activate_stage5_ip_config_result_x_fcn(addr_family), - addr_family); -} - -NMDeviceIPState -nm_device_activate_get_ip_state(NMDevice *self, int addr_family) -{ - const int IS_IPv4 = NM_IS_IPv4(addr_family); - - g_return_val_if_fail(NM_IS_DEVICE(self), NM_DEVICE_IP_STATE_NONE); - g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NM_DEVICE_IP_STATE_NONE); - - return NM_DEVICE_GET_PRIVATE(self)->ip_state_x[IS_IPv4]; -} - -static void -dad6_add_pending_address(NMDevice * self, - NMPlatform * platform, - int ifindex, - const struct in6_addr *address, - NMIP6Config ** dad6_config) -{ - const NMPlatformIP6Address *pl_addr; - - pl_addr = nm_platform_ip6_address_get(platform, ifindex, address); - if (pl_addr && NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_TENTATIVE) - && !NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_DADFAILED) - && !NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { - _LOGt(LOGD_DEVICE, - "IPv6 DAD: pending address %s", - nm_platform_ip6_address_to_string(pl_addr, NULL, 0)); - - if (!*dad6_config) - *dad6_config = nm_device_ip6_config_new(self); - - nm_ip6_config_add_address(*dad6_config, pl_addr); - } -} - -/* - * Returns a NMIP6Config containing NM-configured addresses which - * have the tentative flag, or NULL if none is present. - */ -static NMIP6Config * -dad6_get_pending_addresses(NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMIP6Config * confs[] = {(NMIP6Config *) applied_config_get_current(&priv->ac_ip6_config), - (NMIP6Config *) applied_config_get_current(&priv->dhcp6.ip6_config), - priv->con_ip_config_6, - (NMIP6Config *) applied_config_get_current(&priv->dev2_ip_config_6)}; - const NMPlatformIP6Address *addr; - NMIP6Config * dad6_config = NULL; - NMDedupMultiIter ipconf_iter; - guint i; - int ifindex; - NMPlatform * platform; - - ifindex = nm_device_get_ip_ifindex(self); - g_return_val_if_fail(ifindex > 0, NULL); - - platform = nm_device_get_platform(self); - - if (priv->ipv6ll_has) { - dad6_add_pending_address(self, platform, ifindex, &priv->ipv6ll_addr, &dad6_config); - } - - /* We are interested only in addresses that we have explicitly configured, - * not in externally added ones. - */ - for (i = 0; i < G_N_ELEMENTS(confs); i++) { - if (!confs[i]) - continue; - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) { - dad6_add_pending_address(self, platform, ifindex, &addr->address, &dad6_config); - } + if (!nm_platform_sysctl_set( + nm_device_get_platform(self), + NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv6/conf/all/forwarding"), + "1")) { + _LOGW_ipshared(AF_INET6, "failure to enable ipv6 forwarding"); + _dev_ipsharedx_set_state(self, AF_INET6, NM_DEVICE_IP_STATE_FAILED); + _dev_ip_state_check_async(self, AF_INET6); + return; } - return dad6_config; + _dev_ipsharedx_set_state(self, AF_INET6, NM_DEVICE_IP_STATE_READY); + _dev_ip_state_check_async(self, AF_INET6); } /*****************************************************************************/ @@ -12302,21 +12203,6 @@ act_request_set(NMDevice *self, NMActRequest *act_request) } } -static void -dnsmasq_cleanup(NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - if (!priv->dnsmasq_manager) - return; - - nm_clear_g_signal_handler(priv->dnsmasq_manager, &priv->dnsmasq_state_id); - - nm_dnsmasq_manager_stop(priv->dnsmasq_manager); - g_object_unref(priv->dnsmasq_manager); - priv->dnsmasq_manager = NULL; -} - gboolean nm_device_is_nm_owned(NMDevice *self) { @@ -12333,10 +12219,10 @@ nm_device_is_nm_owned(NMDevice *self) static gboolean delete_on_deactivate_link_delete(gpointer user_data) { - DeleteOnDeactivateData *data = user_data; - nm_auto_unref_object NMDevice *self = data->device; - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - gs_free_error GError *error = NULL; + DeleteOnDeactivateData *data = user_data; + nm_auto_unref_object NMDevice *self = data->device; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gs_free_error GError *error = NULL; _LOGD(LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link (id=%u)", @@ -12375,7 +12261,7 @@ delete_on_deactivate_unschedule(NMDevice *self) static void delete_on_deactivate_check_and_schedule(NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); DeleteOnDeactivateData *data; if (!priv->nm_owned) @@ -12401,40 +12287,32 @@ delete_on_deactivate_check_and_schedule(NMDevice *self) } static void -_cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type) +_cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gboolean from_reapply) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_NONE); + _dev_ipsharedx_cleanup(self, addr_family); - if (nm_clear_g_source(&priv->queued_ip_config_id_x[IS_IPv4])) { - _LOGD(LOGD_DEVICE, - "clearing queued IP%c config change", - nm_utils_addr_family_to_char(addr_family)); - } + _dev_ipdev_cleanup(self, AF_UNSPEC); + _dev_ipdev_cleanup(self, addr_family); - if (IS_IPv4) { - dhcp4_cleanup(self, cleanup_type, FALSE); - arp_cleanup(self); - dnsmasq_cleanup(self); - ipv4ll_cleanup(self); - g_slist_free_full(priv->acd.dad_list, (GDestroyNotify) nm_acd_manager_free); - priv->acd.dad_list = NULL; - } else { - g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); - priv->dad6_failed_addrs = NULL; - g_clear_object(&priv->dad6_ip6_config); - dhcp6_cleanup(self, cleanup_type, FALSE); - nm_clear_g_source(&priv->linklocal6_timeout_id); - addrconf6_cleanup(self); - } + _dev_ipdhcpx_cleanup(self, addr_family, TRUE, FALSE); + + if (!IS_IPv4) + _dev_ipac6_cleanup(self); + + _dev_ipllx_cleanup(self, addr_family); + + _dev_ipmanual_cleanup(self); + + _dev_ip_state_cleanup(self, AF_UNSPEC, from_reapply); + _dev_ip_state_cleanup(self, addr_family, from_reapply); } gboolean -_nm_device_hash_check_invalid_keys(GHashTable * hash, - const char * setting_name, - GError ** error, +_nm_device_hash_check_invalid_keys(GHashTable *hash, + const char *setting_name, + GError **error, const char *const *whitelist) { guint found_whitelisted_keys = 0; @@ -12469,8 +12347,8 @@ _nm_device_hash_check_invalid_keys(GHashTable * hash, if (error) { GHashTableIter iter; - const char * k = NULL; - const char * first_invalid_key = NULL; + const char *k = NULL; + const char *first_invalid_key = NULL; g_hash_table_iter_init(&iter, hash); while (g_hash_table_iter_next(&iter, (gpointer *) &k, NULL)) { @@ -12499,128 +12377,6 @@ _nm_device_hash_check_invalid_keys(GHashTable * hash, return FALSE; } -void -nm_device_reactivate_ip_config(NMDevice * self, - int addr_family, - NMSettingIPConfig *s_ip_old, - NMSettingIPConfig *s_ip_new) -{ - const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMDevicePrivate *priv; - const char * method_old; - const char * method_new; - - g_return_if_fail(NM_IS_DEVICE(self)); - - priv = NM_DEVICE_GET_PRIVATE(self); - - if (priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_NONE) - return; - - g_clear_object(&priv->con_ip_config_x[IS_IPv4]); - g_clear_object(&priv->ext_ip_config_x[IS_IPv4]); - if (IS_IPv4) { - g_clear_object(&priv->dev_ip_config_4.current); - } else { - g_clear_object(&priv->ac_ip6_config.current); - g_clear_object(&priv->dhcp6.ip6_config.current); - } - g_clear_object(&priv->dev2_ip_config_x[IS_IPv4].current); - - if (!IS_IPv4) { - if (priv->ipv6ll_handle && !IN6_IS_ADDR_UNSPECIFIED(&priv->ipv6ll_addr)) - priv->ipv6ll_has = TRUE; - } - - priv->con_ip_config_x[IS_IPv4] = nm_device_ip_config_new(self, addr_family); - - if (IS_IPv4) { - nm_ip4_config_merge_setting(priv->con_ip_config_4, - s_ip_new, - _prop_get_connection_mdns(self), - _prop_get_connection_llmnr(self), - _prop_get_connection_dns_over_tls(self), - nm_device_get_route_table(self, AF_INET), - nm_device_get_route_metric(self, AF_INET)); - } else { - nm_ip6_config_merge_setting(priv->con_ip_config_6, - s_ip_new, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6)); - } - - method_old = (s_ip_old ? nm_setting_ip_config_get_method(s_ip_old) : NULL) - ?: (IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED - : NM_SETTING_IP6_CONFIG_METHOD_IGNORE); - method_new = (s_ip_new ? nm_setting_ip_config_get_method(s_ip_new) : NULL) - ?: (IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED - : NM_SETTING_IP6_CONFIG_METHOD_IGNORE); - - if (!nm_streq0(method_old, method_new)) { - _cleanup_ip_pre(self, addr_family, CLEANUP_TYPE_DECONFIGURE); - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_WAIT); - if (!nm_device_activate_stage3_ip_start(self, addr_family)) { - _LOGW(LOGD_IP4, - "Failed to apply IPv%c configuration", - nm_utils_addr_family_to_char(addr_family)); - } - return; - } - - if (s_ip_old && s_ip_new) { - gint64 metric_old, metric_new; - - /* For dynamic IP methods (DHCP, IPv4LL, WWAN) the route metric is - * set at activation/renewal time using the value from static - * configuration. To support runtime change we need to update the - * dynamic configuration in place and tell the DHCP client the new - * value to use for future renewals. - */ - metric_old = nm_setting_ip_config_get_route_metric(s_ip_old); - metric_new = nm_setting_ip_config_get_route_metric(s_ip_new); - - if (metric_old != metric_new) { - if (IS_IPv4) { - if (priv->dev_ip_config_4.orig) { - nm_ip4_config_update_routes_metric((NMIP4Config *) priv->dev_ip_config_4.orig, - nm_device_get_route_metric(self, AF_INET)); - } - if (priv->dev2_ip_config_4.orig) { - nm_ip4_config_update_routes_metric((NMIP4Config *) priv->dev2_ip_config_4.orig, - nm_device_get_route_metric(self, AF_INET)); - } - if (priv->dhcp_data_4.client) { - nm_dhcp_client_set_route_metric(priv->dhcp_data_4.client, - nm_device_get_route_metric(self, AF_INET)); - } - } else { - if (priv->ac_ip6_config.orig) { - nm_ip6_config_update_routes_metric((NMIP6Config *) priv->ac_ip6_config.orig, - nm_device_get_route_metric(self, AF_INET6)); - } - if (priv->dhcp6.ip6_config.orig) { - nm_ip6_config_update_routes_metric((NMIP6Config *) priv->dhcp6.ip6_config.orig, - nm_device_get_route_metric(self, AF_INET6)); - } - if (priv->dev2_ip_config_6.orig) { - nm_ip6_config_update_routes_metric((NMIP6Config *) priv->dev2_ip_config_6.orig, - nm_device_get_route_metric(self, AF_INET6)); - } - if (priv->dhcp_data_6.client) { - nm_dhcp_client_set_route_metric(priv->dhcp_data_6.client, - nm_device_get_route_metric(self, AF_INET6)); - } - } - } - } - - if (nm_device_get_ip_ifindex(self) > 0 && !ip_config_merge_and_apply(self, addr_family, TRUE)) { - _LOGW(LOGD_IPX(IS_IPv4), - "Failed to reapply IPv%c configuration", - nm_utils_addr_family_to_char(addr_family)); - } -} - static void _pacrunner_manager_add(NMDevice *self) { @@ -12629,10 +12385,8 @@ _pacrunner_manager_add(NMDevice *self) nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id); priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(), - priv->proxy_config, nm_device_get_ip_iface(self), - NULL, - NULL); + nm_device_get_l3cd(self, TRUE)); } static void @@ -12640,19 +12394,19 @@ reactivate_proxy_config(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (!priv->pacrunner_conf_id) - return; - nm_device_set_proxy_config(self, priv->dhcp4.pac_url); - _pacrunner_manager_add(self); + if (priv->pacrunner_conf_id) + _pacrunner_manager_add(self); } +/*****************************************************************************/ + static gboolean -can_reapply_change(NMDevice * self, +can_reapply_change(NMDevice *self, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { if (nm_streq(setting_name, NM_SETTING_CONNECTION_SETTING_NAME)) { /* Whitelist allowed properties from "connection" setting which are @@ -12730,20 +12484,19 @@ reapply_connection(NMDevice *self, NMConnection *con_old, NMConnection *con_new) * Return: %FALSE if the new configuration can not be reapplied. */ static gboolean -check_and_reapply_connection(NMDevice * self, +check_and_reapply_connection(NMDevice *self, NMConnection *connection, guint64 version_id, - char ** audit_args, - GError ** error) -{ - NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * applied = nm_device_get_applied_connection(self); - gs_unref_object NMConnection *applied_clone = NULL; - gs_unref_hashtable GHashTable *diffs = NULL; - NMConnection * con_old, *con_new; - NMSettingIPConfig * s_ip4_old, *s_ip4_new; - NMSettingIPConfig * s_ip6_old, *s_ip6_new; + char **audit_args, + GError **error) +{ + NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMConnection *applied = nm_device_get_applied_connection(self); + gs_unref_object NMConnection *applied_clone = NULL; + gs_unref_hashtable GHashTable *diffs = NULL; + NMConnection *con_old; + NMConnection *con_new; GHashTableIter iter; if (priv->state < NM_DEVICE_STATE_PREPARE || priv->state > NM_DEVICE_STATE_ACTIVATED) { @@ -12771,7 +12524,7 @@ check_and_reapply_connection(NMDevice * self, * check for unsupported changes and reject to reapply *************************************************************************/ if (diffs) { - char * setting_name; + char *setting_name; GHashTable *setting_diff; g_hash_table_iter_init(&iter, diffs); @@ -12792,11 +12545,11 @@ check_and_reapply_connection(NMDevice * self, && version_id != nm_active_connection_version_id_get( (NMActiveConnection *) priv->act_request.obj)) { - g_set_error_literal( - error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_VERSION_ID_MISMATCH, - "Reapply failed because device changed in the meantime and the version-id mismatches"); + g_set_error_literal(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_VERSION_ID_MISMATCH, + "Reapply failed because device changed in the meantime and the " + "version-id mismatches"); return FALSE; } @@ -12814,7 +12567,7 @@ check_and_reapply_connection(NMDevice * self, diffs ? "" : " (unmodified)"); if (diffs) { - NMConnection * connection_clean = connection; + NMConnection *connection_clean = connection; gs_unref_object NMConnection *connection_clean_free = NULL; { @@ -12859,11 +12612,9 @@ check_and_reapply_connection(NMDevice * self, } else con_old = con_new = applied; - priv->v4_commit_first_time = TRUE; - priv->v6_commit_first_time = TRUE; - priv->v4_route_table_initialized = FALSE; priv->v6_route_table_initialized = FALSE; + priv->l3config_merge_flags_has = FALSE; /************************************************************************** * Reapply changes @@ -12880,20 +12631,21 @@ check_and_reapply_connection(NMDevice * self, lldp_setup(self, NM_TERNARY_DEFAULT); if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) { - s_ip4_old = nm_connection_get_setting_ip4_config(con_old); - s_ip4_new = nm_connection_get_setting_ip4_config(con_new); - s_ip6_old = nm_connection_get_setting_ip6_config(con_old); - s_ip6_new = nm_connection_get_setting_ip6_config(con_new); - /* Allow reapply of MTU */ priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; - nm_device_reactivate_ip_config(self, AF_INET, s_ip4_old, s_ip4_new); - nm_device_reactivate_ip_config(self, AF_INET6, s_ip6_old, s_ip6_new); + if (nm_g_hash_table_lookup(diffs, NM_SETTING_IP4_CONFIG_SETTING_NAME)) + priv->ip_data_4.do_reapply = TRUE; + if (nm_g_hash_table_lookup(diffs, NM_SETTING_IP6_CONFIG_SETTING_NAME)) + priv->ip_data_6.do_reapply = TRUE; + + nm_device_activate_schedule_stage3_ip_config(self, FALSE); _routing_rules_sync(self, NM_TERNARY_TRUE); reactivate_proxy_config(self); + + nm_device_l3cfg_commit(self, NM_L3_CFG_COMMIT_TYPE_REAPPLY, FALSE); } if (priv->state >= NM_DEVICE_STATE_IP_CHECK) @@ -12919,17 +12671,17 @@ typedef struct { } ReapplyData; static void -reapply_cb(NMDevice * self, +reapply_cb(NMDevice *self, GDBusMethodInvocation *context, - NMAuthSubject * subject, - GError * error, + NMAuthSubject *subject, + GError *error, gpointer user_data) { - ReapplyData * reapply_data = user_data; - guint64 version_id = 0; - gs_unref_object NMConnection *connection = NULL; - GError * local = NULL; - gs_free char * audit_args = NULL; + ReapplyData *reapply_data = user_data; + guint64 version_id = 0; + gs_unref_object NMConnection *connection = NULL; + GError *local = NULL; + gs_free char *audit_args = NULL; if (reapply_data) { connection = reapply_data->connection; @@ -12972,20 +12724,20 @@ reapply_cb(NMDevice * self, } static void -impl_device_reapply(NMDBusObject * obj, +impl_device_reapply(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * dbus_connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) -{ - NMDevice * self = NM_DEVICE(obj); - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMSettingsConnection *settings_connection; - NMConnection * connection = NULL; - GError * error = NULL; - ReapplyData * reapply_data; + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *dbus_connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) +{ + NMDevice *self = NM_DEVICE(obj); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMSettingsConnection *settings_connection; + NMConnection *connection = NULL; + GError *error = NULL; + ReapplyData *reapply_data; gs_unref_variant GVariant *settings = NULL; guint64 version_id; guint32 flags; @@ -13063,20 +12815,20 @@ impl_device_reapply(NMDBusObject * obj, /*****************************************************************************/ static void -impl_device_get_applied_connection(NMDBusObject * obj, +impl_device_get_applied_connection(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) -{ - NMDevice * self = NM_DEVICE(obj); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) +{ + NMDevice *self = NM_DEVICE(obj); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gs_free_error GError *error = NULL; - NMConnection * applied_connection; + NMConnection *applied_connection; guint32 flags; - GVariant * var_settings; + GVariant *var_settings; g_variant_get(parameters, "(u)", &flags); @@ -13123,105 +12875,15 @@ impl_device_get_applied_connection(NMDBusObject * obj, /*****************************************************************************/ -typedef struct { - gint64 timestamp_ms; - bool dirty; -} IP6RoutesTemporaryNotAvailableData; - -static gboolean -_rt6_temporary_not_available_timeout(gpointer user_data) -{ - NMDevice * self = NM_DEVICE(user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - priv->rt6_temporary_not_available_id = 0; - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - - return G_SOURCE_REMOVE; -} - -static gboolean -_rt6_temporary_not_available_set(NMDevice *self, GPtrArray *temporary_not_available) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - IP6RoutesTemporaryNotAvailableData *data; - GHashTableIter iter; - gint64 now_ms, oldest_ms; - const gint64 MAX_AGE_MS = 20000; - guint i; - gboolean success = TRUE; - - if (!temporary_not_available || !temporary_not_available->len) { - /* nothing outstanding. Clear tracking the routes. */ - nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref); - nm_clear_g_source(&priv->rt6_temporary_not_available_id); - return success; - } - - if (priv->rt6_temporary_not_available) { - g_hash_table_iter_init(&iter, priv->rt6_temporary_not_available); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &data)) - data->dirty = TRUE; - } else { - priv->rt6_temporary_not_available = - g_hash_table_new_full((GHashFunc) nmp_object_id_hash, - (GEqualFunc) nmp_object_id_equal, - (GDestroyNotify) nmp_object_unref, - nm_g_slice_free_fcn(IP6RoutesTemporaryNotAvailableData)); - } - - now_ms = nm_utils_get_monotonic_timestamp_msec(); - oldest_ms = now_ms; - - for (i = 0; i < temporary_not_available->len; i++) { - const NMPObject *o = temporary_not_available->pdata[i]; - - data = g_hash_table_lookup(priv->rt6_temporary_not_available, o); - if (data) { - if (!data->dirty) - continue; - data->dirty = FALSE; - nm_assert(data->timestamp_ms > 0 && data->timestamp_ms <= now_ms); - if (now_ms > data->timestamp_ms + MAX_AGE_MS) { - /* timeout. Could not add this address. */ - _LOGW(LOGD_DEVICE, - "failure to add IPv6 route: %s", - nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0)); - success = FALSE; - } else - oldest_ms = MIN(data->timestamp_ms, oldest_ms); - continue; - } - - data = g_slice_new0(IP6RoutesTemporaryNotAvailableData); - data->timestamp_ms = now_ms; - g_hash_table_insert(priv->rt6_temporary_not_available, (gpointer) nmp_object_ref(o), data); - } - - g_hash_table_iter_init(&iter, priv->rt6_temporary_not_available); - while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &data)) { - if (data->dirty) - g_hash_table_iter_remove(&iter); - } - - nm_clear_g_source(&priv->rt6_temporary_not_available_id); - priv->rt6_temporary_not_available_id = - g_timeout_add(oldest_ms + MAX_AGE_MS - now_ms, _rt6_temporary_not_available_timeout, self); - - return success; -} - -/*****************************************************************************/ - static void -disconnect_cb(NMDevice * self, +disconnect_cb(NMDevice *self, GDBusMethodInvocation *context, - NMAuthSubject * subject, - GError * error, + NMAuthSubject *subject, + GError *error, gpointer user_data) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - GError * local = NULL; + GError *local = NULL; if (error) { g_dbus_method_invocation_return_gerror(context, error); @@ -13269,17 +12931,17 @@ _clear_queued_act_request(NMDevicePrivate *priv, NMActiveConnectionStateReason a } static void -impl_device_disconnect(NMDBusObject * obj, +impl_device_disconnect(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * dbus_connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *dbus_connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { - NMDevice * self = NM_DEVICE(obj); + NMDevice *self = NM_DEVICE(obj); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; + NMConnection *connection; if (!priv->act_request.obj) { g_dbus_method_invocation_return_error_literal(invocation, @@ -13303,10 +12965,10 @@ impl_device_disconnect(NMDBusObject * obj, } static void -delete_cb(NMDevice * self, +delete_cb(NMDevice *self, GDBusMethodInvocation *context, - NMAuthSubject * subject, - GError * error, + NMAuthSubject *subject, + GError *error, gpointer user_data) { GError *local = NULL; @@ -13331,13 +12993,13 @@ delete_cb(NMDevice * self, } static void -impl_device_delete(NMDBusObject * obj, +impl_device_delete(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { NMDevice *self = NM_DEVICE(obj); @@ -13428,7 +13090,7 @@ static gboolean _carrier_wait_check_act_request_must_queue(NMDevice *self, NMActRequest *req) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; + NMConnection *connection; /* If we have carrier or if we are not waiting for it, the activation * request is not blocked waiting for carrier. */ @@ -13477,11 +13139,11 @@ _carrier_wait_check_act_request_must_queue(NMDevice *self, NMActRequest *req) } void -nm_device_disconnect_active_connection(NMActiveConnection * active, +nm_device_disconnect_active_connection(NMActiveConnection *active, NMDeviceStateReason device_reason, NMActiveConnectionStateReason active_reason) { - NMDevice * self; + NMDevice *self; NMDevicePrivate *priv; g_return_if_fail(NM_IS_ACTIVE_CONNECTION(active)); @@ -13592,324 +13254,44 @@ nm_device_is_activating(NMDevice *self) * handler is actually run. If there's an activation handler scheduled * we're activating anyway. */ - return priv->activation_source_id_4 != 0; + return !!priv->activation_idle_source; } -NMProxyConfig * -nm_device_get_proxy_config(NMDevice *self) -{ - g_return_val_if_fail(NM_IS_DEVICE(self), NULL); - - return NM_DEVICE_GET_PRIVATE(self)->proxy_config; -} - -static void -nm_device_set_proxy_config(NMDevice *self, const char *pac_url) -{ - NMDevicePrivate *priv; - NMConnection * connection; - NMSettingProxy * s_proxy = NULL; - - g_return_if_fail(NM_IS_DEVICE(self)); - - priv = NM_DEVICE_GET_PRIVATE(self); - - g_clear_object(&priv->proxy_config); - priv->proxy_config = nm_proxy_config_new(); - - if (pac_url) { - nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO); - nm_proxy_config_set_pac_url(priv->proxy_config, pac_url); - _LOGD(LOGD_PROXY, "proxy: PAC url \"%s\"", pac_url); - } else - nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE); - - connection = nm_device_get_applied_connection(self); - if (connection) - s_proxy = nm_connection_get_setting_proxy(connection); - - if (s_proxy) - nm_proxy_config_merge_setting(priv->proxy_config, s_proxy); -} - -/* IP Configuration stuff */ NMDhcpConfig * nm_device_get_dhcp_config(NMDevice *self, int addr_family) { - const int IS_IPv4 = NM_IS_IPv4(addr_family); - g_return_val_if_fail(NM_IS_DEVICE(self), NULL); - nm_assert_addr_family(addr_family); - - return NM_DEVICE_GET_PRIVATE(self)->dhcp_data_x[IS_IPv4].config; + return NM_DEVICE_GET_PRIVATE(self)->ipdhcp_data_x[NM_IS_IPv4(addr_family)].config; } -NMIP4Config * -nm_device_get_ip4_config(NMDevice *self) +NML3Cfg * +nm_device_get_l3cfg(NMDevice *self) { g_return_val_if_fail(NM_IS_DEVICE(self), NULL); - return NM_DEVICE_GET_PRIVATE(self)->ip_config_4; + return NM_DEVICE_GET_PRIVATE(self)->l3cfg; } -static gboolean -nm_device_set_ip_config(NMDevice * self, - int addr_family, - NMIPConfig *new_config, - gboolean commit, - GPtrArray * ip4_dev_route_blacklist) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - const int IS_IPv4 = NM_IS_IPv4(addr_family); - NMIPConfig * old_config; - gboolean has_changes = FALSE; - gboolean success = TRUE; - NMSettingsConnection * settings_connection; - NMIPRouteTableSyncMode route_table_sync_mode; - - nm_assert_addr_family(addr_family); - nm_assert(!new_config || nm_ip_config_get_addr_family(new_config) == addr_family); - nm_assert(!new_config - || (new_config && ({ - int ip_ifindex = nm_device_get_ip_ifindex(self); - - (ip_ifindex > 0 && ip_ifindex == nm_ip_config_get_ifindex(new_config)); - }))); - nm_assert(IS_IPv4 || !ip4_dev_route_blacklist); - - if (commit && new_config) - route_table_sync_mode = _get_route_table_sync_mode_stateful(self, addr_family); - else - route_table_sync_mode = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE; - - _LOGD(LOGD_IPX(IS_IPv4), - "ip%c-config: update (commit=%d, new-config=" NM_HASH_OBFUSCATE_PTR_FMT - ", route-table-sync-mode=%d)", - nm_utils_addr_family_to_char(addr_family), - commit, - NM_HASH_OBFUSCATE_PTR(new_config), - (int) route_table_sync_mode); - - /* Always commit to nm-platform to update lifetimes */ - if (commit && new_config) { - _commit_mtu(self, IS_IPv4 ? NM_IP4_CONFIG(new_config) : priv->ip_config_4); - - if (IS_IPv4) { - success = nm_ip4_config_commit(NM_IP4_CONFIG(new_config), - nm_device_get_platform(self), - route_table_sync_mode); - nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self), - nm_ip_config_get_ifindex(new_config), - ip4_dev_route_blacklist); - } else { - gs_unref_ptrarray GPtrArray *temporary_not_available = NULL; - - success = nm_ip6_config_commit(NM_IP6_CONFIG(new_config), - nm_device_get_platform(self), - route_table_sync_mode, - &temporary_not_available); - - if (!_rt6_temporary_not_available_set(self, temporary_not_available)) - success = FALSE; - } - } - - old_config = priv->ip_config_x[IS_IPv4]; - - if (new_config && old_config) { - /* has_changes is set only on relevant changes, because when the configuration changes, - * this causes a re-read and reset. This should only happen for relevant changes */ - nm_ip_config_replace(old_config, new_config, &has_changes); - if (has_changes) { - _LOGD(LOGD_IPX(IS_IPv4), - "ip%c-config: update IP Config instance (%s)", - nm_utils_addr_family_to_char(addr_family), - nm_dbus_object_get_path(NM_DBUS_OBJECT(old_config))); - } - } else if (new_config /*&& !old_config*/) { - has_changes = TRUE; - priv->ip_config_x[IS_IPv4] = g_object_ref(new_config); - if (!nm_dbus_object_is_exported(NM_DBUS_OBJECT(new_config))) - nm_dbus_object_export(NM_DBUS_OBJECT(new_config)); - - _LOGD(LOGD_IPX(IS_IPv4), - "ip%c-config: set IP Config instance (%s)", - nm_utils_addr_family_to_char(addr_family), - nm_dbus_object_get_path(NM_DBUS_OBJECT(new_config))); - } else if (old_config /*&& !new_config*/) { - has_changes = TRUE; - priv->ip_config_x[IS_IPv4] = NULL; - _LOGD(LOGD_IPX(IS_IPv4), - "ip%c-config: clear IP Config instance (%s)", - nm_utils_addr_family_to_char(addr_family), - nm_dbus_object_get_path(NM_DBUS_OBJECT(old_config))); - if (IS_IPv4) { - /* Device config is invalid if combined config is invalid */ - applied_config_clear(&priv->dev_ip_config_4); - } else - priv->needs_ip6_subnet = FALSE; - } - - if (has_changes) { - if (old_config != priv->ip_config_x[IS_IPv4]) - _notify(self, IS_IPv4 ? PROP_IP4_CONFIG : PROP_IP6_CONFIG); - - g_signal_emit(self, - signals[IS_IPv4 ? IP4_CONFIG_CHANGED : IP6_CONFIG_CHANGED], - 0, - priv->ip_config_x[IS_IPv4], - old_config); - - if (old_config != priv->ip_config_x[IS_IPv4]) - nm_dbus_object_clear_and_unexport(&old_config); - - if (nm_device_sys_iface_state_is_external(self) - && (settings_connection = nm_device_get_settings_connection(self)) - && NM_FLAGS_HAS(nm_settings_connection_get_flags(settings_connection), - NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL) - && nm_active_connection_get_activation_type(NM_ACTIVE_CONNECTION(priv->act_request.obj)) - == NM_ACTIVATION_TYPE_EXTERNAL) { - gs_unref_object NMConnection *new_connection = NULL; - - new_connection = nm_simple_connection_new_clone( - nm_settings_connection_get_connection(settings_connection)); - - nm_connection_add_setting( - new_connection, - IS_IPv4 ? nm_ip4_config_create_setting(priv->ip_config_4) - : nm_ip6_config_create_setting(priv->ip_config_6, - _get_maybe_ipv6_disabled(self))); - - nm_settings_connection_update(settings_connection, - new_connection, - NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY, - NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, - NM_SETTINGS_CONNECTION_INT_FLAGS_NONE, - NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET, - "update-external", - NULL); - } - - nm_device_queue_recheck_assume(self); - - if (!IS_IPv4) { - if (priv->ndisc) - ndisc_set_router_config(priv->ndisc, self); - } - } - - nm_assert(!old_config || old_config == priv->ip_config_x[IS_IPv4]); - - return success; -} - -static gboolean -_replace_vpn_config_in_list(GSList **plist, GObject *old, GObject *new) -{ - GSList *old_link; - - /* Below, assert that @new is not yet tracked, but still behave - * correctly in any case. Don't complain for missing @old since - * it could have been removed when the parent device became - * unmanaged. */ - - if (old && (old_link = g_slist_find(*plist, old))) { - if (old != new) { - if (new) - old_link->data = g_object_ref(new); - else - *plist = g_slist_delete_link(*plist, old_link); - g_object_unref(old); - } - return TRUE; - } - - if (new) { - if (!g_slist_find(*plist, new)) - *plist = g_slist_append(*plist, g_object_ref(new)); - else - g_return_val_if_reached(TRUE); - return TRUE; - } - - return FALSE; -} - -void -nm_device_replace_vpn4_config(NMDevice *self, NMIP4Config *old, NMIP4Config *config) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - nm_assert(!old || NM_IS_IP4_CONFIG(old)); - nm_assert(!config || NM_IS_IP4_CONFIG(config)); - nm_assert(!old || nm_ip4_config_get_ifindex(old) == nm_device_get_ip_ifindex(self)); - nm_assert(!config || nm_ip4_config_get_ifindex(config) == nm_device_get_ip_ifindex(self)); - - if (!_replace_vpn_config_in_list(&priv->vpn_configs_4, (GObject *) old, (GObject *) config)) - return; - - /* NULL to use existing configs */ - if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) - _LOGW(LOGD_IP4, "failed to set VPN routes for device"); -} - -void -nm_device_set_dev2_ip_config(NMDevice *self, int addr_family, NMIPConfig *config) +const NML3ConfigData * +nm_device_get_l3cd(NMDevice *self, gboolean get_commited) { NMDevicePrivate *priv; - const int IS_IPv4 = NM_IS_IPv4(addr_family); - g_return_if_fail(NM_IS_DEVICE(self)); - g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - g_return_if_fail(!config || nm_ip_config_get_addr_family(config) == addr_family); + g_return_val_if_fail(NM_IS_DEVICE(self), NULL); priv = NM_DEVICE_GET_PRIVATE(self); - applied_config_init(&priv->dev2_ip_config_x[IS_IPv4], config); - if (!ip_config_merge_and_apply(self, addr_family, TRUE)) { - _LOGW(LOGD_IP, - "failed to set extra device IPv%c configuration", - nm_utils_addr_family_to_char(addr_family)); - } -} - -void -nm_device_replace_vpn6_config(NMDevice *self, NMIP6Config *old, NMIP6Config *config) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMDeviceState state; - - nm_assert(!old || NM_IS_IP6_CONFIG(old)); - nm_assert(!old || nm_ip6_config_get_ifindex(old) > 0); - nm_assert(!old || nm_device_get_ip_ifindex(self) == 0 - || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(old)); - nm_assert(!config || NM_IS_IP6_CONFIG(config)); - nm_assert(!config || nm_ip6_config_get_ifindex(config) > 0); - nm_assert(!config || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(config)); - - if (!_replace_vpn_config_in_list(&priv->vpn_configs_6, (GObject *) old, (GObject *) config)) - return; - - state = nm_device_get_state(self); - if (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_ACTIVATED) { - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "failed to set VPN routes for device"); - } -} - -NMIP6Config * -nm_device_get_ip6_config(NMDevice *self) -{ - g_return_val_if_fail(NM_IS_DEVICE(self), NULL); + if (!priv->l3cfg) + return NULL; - return NM_DEVICE_GET_PRIVATE(self)->ip_config_6; + return nm_l3cfg_get_combined_l3cd(priv->l3cfg, get_commited); } /*****************************************************************************/ static gboolean -dispatcher_cleanup(NMDevice *self) +_dispatcher_cleanup(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -13923,9 +13305,9 @@ dispatcher_cleanup(NMDevice *self) } static void -dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data) +_dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); + NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); g_return_if_fail(call_id == priv->dispatcher.call_id); @@ -13943,7 +13325,7 @@ ip_check_pre_up(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (dispatcher_cleanup(self)) + if (_dispatcher_cleanup(self)) nm_assert_not_reached(); priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES; @@ -13951,11 +13333,11 @@ ip_check_pre_up(NMDevice *self) if (!nm_dispatcher_call_device(NM_DISPATCHER_ACTION_PRE_UP, self, NULL, - dispatcher_complete_proceed_state, + _dispatcher_complete_proceed_state, self, &priv->dispatcher.call_id)) { /* Just proceed on errors */ - dispatcher_complete_proceed_state(0, self); + _dispatcher_complete_proceed_state(0, self); } } @@ -13985,10 +13367,10 @@ ip_check_gw_ping_cleanup(NMDevice *self) static gboolean spawn_ping(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - gs_free char * str_timeout = NULL; - gs_free char * tmp_str = NULL; - const char * args[] = {priv->gw_ping.binary, + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gs_free char *str_timeout = NULL; + gs_free char *tmp_str = NULL; + const char *args[] = {priv->gw_ping.binary, "-I", nm_device_get_ip_iface(self), "-c", @@ -13997,7 +13379,7 @@ spawn_ping(NMDevice *self) NULL, priv->gw_ping.address, NULL}; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; gboolean ret; args[6] = str_timeout = g_strdup_printf("%u", priv->gw_ping.deadline); @@ -14026,7 +13408,7 @@ spawn_ping(NMDevice *self) static gboolean respawn_ping_cb(gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); + NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); priv->gw_ping.watch = 0; @@ -14044,7 +13426,7 @@ respawn_ping_cb(gpointer user_data) static void ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); + NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMLogDomain log_domain = priv->gw_ping.log_domain; gboolean success = FALSE; @@ -14078,7 +13460,7 @@ ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data) static gboolean ip_check_ping_timeout_cb(gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); + NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); priv->gw_ping.timeout = 0; @@ -14091,7 +13473,7 @@ ip_check_ping_timeout_cb(gpointer user_data) } static gboolean -start_ping(NMDevice * self, +start_ping(NMDevice *self, NMLogDomain log_domain, const char *binary, const char *address, @@ -14120,11 +13502,11 @@ start_ping(NMDevice * self, static void nm_device_start_ip_check(NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMConnection * connection; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMConnection *connection; NMSettingConnection *s_con; guint timeout = 0; - const char * ping_binary = NULL; + const char *ping_binary = NULL; char buf[NM_UTILS_INET_ADDRSTRLEN]; NMLogDomain log_domain = LOGD_IP4; @@ -14135,8 +13517,8 @@ nm_device_start_ip_check(NMDevice *self) g_return_if_fail(!priv->gw_ping.watch); g_return_if_fail(!priv->gw_ping.timeout); g_return_if_fail(!priv->gw_ping.pid); - g_return_if_fail(priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE - || priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE); + g_return_if_fail(priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY + || priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY); connection = nm_device_get_applied_connection(self); g_assert(connection); @@ -14147,17 +13529,21 @@ nm_device_start_ip_check(NMDevice *self) buf[0] = '\0'; if (timeout) { - const NMPObject *gw; + const NMPObject *gw; + const NML3ConfigData *l3cd; - if (priv->ip_config_4 && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) { - gw = nm_ip4_config_best_default_route_get(priv->ip_config_4); + l3cd = priv->l3cfg ? nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE) : NULL; + if (!l3cd) { + /* pass */ + } else if (priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY) { + gw = nm_l3_config_data_get_best_default_route(l3cd, AF_INET); if (gw) { _nm_utils_inet4_ntop(NMP_OBJECT_CAST_IP4_ROUTE(gw)->gateway, buf); ping_binary = nm_utils_find_helper("ping", "/usr/bin/ping", NULL); log_domain = LOGD_IP4; } - } else if (priv->ip_config_6 && priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) { - gw = nm_ip6_config_best_default_route_get(priv->ip_config_6); + } else if (priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY) { + gw = nm_l3_config_data_get_best_default_route(l3cd, AF_INET6); if (gw) { _nm_utils_inet6_ntop(&NMP_OBJECT_CAST_IP6_ROUTE(gw)->gateway, buf); ping_binary = nm_utils_find_helper("ping6", "/usr/bin/ping6", NULL); @@ -14179,7 +13565,7 @@ nm_device_start_ip_check(NMDevice *self) static gboolean carrier_wait_timeout(gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); + NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); priv->carrier_wait_id = 0; @@ -14216,7 +13602,7 @@ _get_carrier_wait_ms(NMDevice *self) gboolean nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean device_is_up = FALSE; NMDeviceCapabilities capabilities; int ifindex; @@ -14297,15 +13683,7 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware) /* Can only get HW address of some devices when they are up */ nm_device_update_hw_address(self); - /* when the link comes up, we must restore IP configuration if necessary. */ - if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) { - if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) - _LOGW(LOGD_IP4, "failed applying IP4 config after bringing link up"); - } - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) { - if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP6, "failed applying IP6 config after bringing link up"); - } + _dev_l3_cfg_commit(self, TRUE); return TRUE; } @@ -14368,381 +13746,6 @@ nm_device_get_firmware_missing(NMDevice *self) return NM_DEVICE_GET_PRIVATE(self)->firmware_missing; } -static void -intersect_ext_config(NMDevice * self, - AppliedConfig *config, - gboolean intersect_addresses, - gboolean intersect_routes) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMIPConfig * ext; - guint32 penalty; - int family; - - if (!config->orig) - return; - - family = nm_ip_config_get_addr_family(config->orig); - penalty = default_route_metric_penalty_get(self, family); - ext = family == AF_INET ? (NMIPConfig *) priv->ext_ip_config_4 - : (NMIPConfig *) priv->ext_ip_config_6; - - if (config->current) { - nm_ip_config_intersect(config->current, - ext, - intersect_addresses, - intersect_routes, - penalty); - } else { - config->current = nm_ip_config_intersect_alloc(config->orig, - ext, - intersect_addresses, - intersect_routes, - penalty); - } -} - -static gboolean -update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - int ifindex; - GSList * iter; - gboolean is_up; - - nm_assert_addr_family(addr_family); - - ifindex = nm_device_get_ip_ifindex(self); - if (!ifindex) - return FALSE; - - is_up = nm_platform_link_is_up(nm_device_get_platform(self), ifindex); - - if (NM_IS_IPv4(addr_family)) { - g_clear_object(&priv->ext_ip_config_4); - priv->ext_ip_config_4 = nm_ip4_config_capture(nm_device_get_multi_index(self), - nm_device_get_platform(self), - ifindex); - if (priv->ext_ip_config_4) { - if (intersect_configs) { - /* This function was called upon external changes. Remove the configuration - * (addresses,routes) that is no longer present externally from the internal - * config. This way, we don't re-add addresses that were manually removed - * by the user. */ - if (priv->con_ip_config_4) { - nm_ip4_config_intersect(priv->con_ip_config_4, - priv->ext_ip_config_4, - TRUE, - is_up, - default_route_metric_penalty_get(self, AF_INET)); - } - - intersect_ext_config(self, &priv->dev_ip_config_4, TRUE, is_up); - intersect_ext_config(self, &priv->dev2_ip_config_4, TRUE, is_up); - - for (iter = priv->vpn_configs_4; iter; iter = iter->next) - nm_ip4_config_intersect(iter->data, priv->ext_ip_config_4, TRUE, is_up, 0); - } - - /* Remove parts from ext_ip_config_4 to only contain the information that - * was configured externally -- we already have the same configuration from - * internal origins. */ - if (priv->con_ip_config_4) { - nm_ip4_config_subtract(priv->ext_ip_config_4, - priv->con_ip_config_4, - default_route_metric_penalty_get(self, AF_INET)); - } - if (applied_config_get_current(&priv->dev_ip_config_4)) { - nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_4, - applied_config_get_current(&priv->dev_ip_config_4), - default_route_metric_penalty_get(self, AF_INET)); - } - if (applied_config_get_current(&priv->dev2_ip_config_4)) { - nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_4, - applied_config_get_current(&priv->dev2_ip_config_4), - default_route_metric_penalty_get(self, AF_INET)); - } - for (iter = priv->vpn_configs_4; iter; iter = iter->next) - nm_ip4_config_subtract(priv->ext_ip_config_4, iter->data, 0); - } - - } else { - nm_assert(!NM_IS_IPv4(addr_family)); - - g_clear_object(&priv->ext_ip_config_6); - g_clear_object(&priv->ext_ip6_config_captured); - priv->ext_ip6_config_captured = - nm_ip6_config_capture(nm_device_get_multi_index(self), - nm_device_get_platform(self), - ifindex, - NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - if (priv->ext_ip6_config_captured) { - priv->ext_ip_config_6 = nm_ip6_config_new_cloned(priv->ext_ip6_config_captured); - - if (intersect_configs) { - /* This function was called upon external changes. Remove the configuration - * (addresses,routes) that is no longer present externally from the internal - * config. This way, we don't re-add addresses that were manually removed - * by the user. */ - if (priv->con_ip_config_6) { - nm_ip6_config_intersect(priv->con_ip_config_6, - priv->ext_ip_config_6, - is_up, - is_up, - default_route_metric_penalty_get(self, AF_INET6)); - } - - intersect_ext_config(self, &priv->ac_ip6_config, is_up, is_up); - intersect_ext_config(self, &priv->dhcp6.ip6_config, is_up, is_up); - intersect_ext_config(self, &priv->dev2_ip_config_6, is_up, is_up); - - for (iter = priv->vpn_configs_6; iter; iter = iter->next) - nm_ip6_config_intersect(iter->data, priv->ext_ip_config_6, is_up, is_up, 0); - - if (is_up && priv->ipv6ll_has - && !nm_ip6_config_lookup_address(priv->ext_ip_config_6, &priv->ipv6ll_addr)) - priv->ipv6ll_has = FALSE; - } - - /* Remove parts from ext_ip_config_6 to only contain the information that - * was configured externally -- we already have the same configuration from - * internal origins. */ - if (priv->con_ip_config_6) { - nm_ip6_config_subtract(priv->ext_ip_config_6, - priv->con_ip_config_6, - default_route_metric_penalty_get(self, AF_INET6)); - } - if (applied_config_get_current(&priv->ac_ip6_config)) { - nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6, - applied_config_get_current(&priv->ac_ip6_config), - default_route_metric_penalty_get(self, AF_INET6)); - } - if (applied_config_get_current(&priv->dhcp6.ip6_config)) { - nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6, - applied_config_get_current(&priv->dhcp6.ip6_config), - default_route_metric_penalty_get(self, AF_INET6)); - } - if (applied_config_get_current(&priv->dev2_ip_config_6)) { - nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6, - applied_config_get_current(&priv->dev2_ip_config_6), - default_route_metric_penalty_get(self, AF_INET6)); - } - for (iter = priv->vpn_configs_6; iter; iter = iter->next) - nm_ip6_config_subtract(priv->ext_ip_config_6, iter->data, 0); - } - } - - return TRUE; -} - -static void -update_ip_config(NMDevice *self, int addr_family) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - nm_assert_addr_family(addr_family); - - if (NM_IS_IPv4(addr_family)) - priv->update_ip_config_completed_v4 = TRUE; - else - priv->update_ip_config_completed_v6 = TRUE; - - if (update_ext_ip_config(self, addr_family, TRUE)) { - if (NM_IS_IPv4(addr_family)) { - if (priv->ext_ip_config_4) - ip_config_merge_and_apply(self, AF_INET, FALSE); - } else { - if (priv->ext_ip6_config_captured) - ip_config_merge_and_apply(self, AF_INET6, FALSE); - } - } -} - -void -nm_device_capture_initial_config(NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - if (!priv->update_ip_config_completed_v4) - update_ip_config(self, AF_INET); - if (!priv->update_ip_config_completed_v6) - update_ip_config(self, AF_INET6); -} - -static gboolean -queued_ip_config_change(NMDevice *self, int addr_family) -{ - NMDevicePrivate *priv; - const int IS_IPv4 = NM_IS_IPv4(addr_family); - - g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE); - - priv = NM_DEVICE_GET_PRIVATE(self); - - /* Wait for any queued state changes */ - if (priv->queued_state.id) - return G_SOURCE_CONTINUE; - - /* If a commit is scheduled, this function would potentially interfere with - * it changing IP configurations before they are applied. Postpone the - * update in such case. - */ - if (priv->activation_source_id_x[IS_IPv4] != 0 - && priv->activation_source_func_x[IS_IPv4] - == activate_stage5_ip_config_result_x_fcn(addr_family)) - return G_SOURCE_CONTINUE; - - priv->queued_ip_config_id_x[IS_IPv4] = 0; - - update_ip_config(self, addr_family); - - if (!IS_IPv4) { - /* Check whether we need to complete waiting for link-local. - * We are also called from an idle handler, so no problem doing state transitions - * now. */ - linklocal6_check_complete(self); - } - - if (!IS_IPv4) { - NMPlatform * platform; - GSList * dad6_failed_addrs, *iter; - const NMPlatformLink *pllink; - - dad6_failed_addrs = g_steal_pointer(&priv->dad6_failed_addrs); - - if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING - && priv->ifindex > 0 && !nm_device_sys_iface_state_is_external(self) - && (platform = nm_device_get_platform(self)) - && (pllink = nm_platform_link_get(platform, priv->ifindex)) - && (pllink->n_ifi_flags & IFF_UP)) { - gboolean need_ipv6ll = FALSE; - NMNDiscConfigMap ndisc_config_changed = NM_NDISC_CONFIG_NONE; - - /* Handle DAD failures */ - for (iter = dad6_failed_addrs; iter; iter = iter->next) { - const NMPObject * obj = iter->data; - const NMPlatformIP6Address *addr; - - if (!nm_ndisc_dad_addr_is_fail_candidate(platform, obj)) - continue; - - addr = NMP_OBJECT_CAST_IP6_ADDRESS(obj); - - _LOGI(LOGD_IP6, - "ipv6: duplicate address check failed for the %s address", - nm_platform_ip6_address_to_string(addr, NULL, 0)); - - if (IN6_IS_ADDR_LINKLOCAL(&addr->address)) - need_ipv6ll = TRUE; - else if (priv->ndisc) - ndisc_config_changed |= nm_ndisc_dad_failed(priv->ndisc, &addr->address, FALSE); - } - - if (ndisc_config_changed != NM_NDISC_CONFIG_NONE) - nm_ndisc_emit_config_change(priv->ndisc, ndisc_config_changed); - - /* If no IPv6 link-local address exists but other addresses do then we - * must add the LL address to remain conformant with RFC 3513 chapter 2.1 - * ("Addressing Model"): "All interfaces are required to have at least - * one link-local unicast address". - */ - if (priv->ip_config_6 && nm_ip6_config_get_num_addresses(priv->ip_config_6)) - need_ipv6ll = TRUE; - if (need_ipv6ll) - check_and_add_ipv6ll_addr(self); - } - - g_slist_free_full(dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); - } - - if (!IS_IPv4) { - /* Check if DAD is still pending */ - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF && priv->dad6_ip6_config - && priv->ext_ip6_config_captured - && !nm_ip6_config_has_any_dad_pending(priv->ext_ip6_config_captured, - priv->dad6_ip6_config)) { - _LOGD(LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated"); - g_clear_object(&priv->dad6_ip6_config); - _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - if (priv->rt6_temporary_not_available) - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - } - } - - set_unmanaged_external_down(self, TRUE); - - return G_SOURCE_REMOVE; -} - -static gboolean -queued_ip4_config_change(gpointer user_data) -{ - return queued_ip_config_change(user_data, AF_INET); -} - -static gboolean -queued_ip6_config_change(gpointer user_data) -{ - return queued_ip_config_change(user_data, AF_INET6); -} - -static void -device_ipx_changed(NMPlatform * platform, - int obj_type_i, - int ifindex, - gconstpointer platform_object, - int change_type_i, - NMDevice * self) -{ - const NMPObjectType obj_type = obj_type_i; - const NMPlatformSignalChangeType change_type = change_type_i; - NMDevicePrivate * priv; - const NMPlatformIP6Address * addr; - - if (nm_device_get_ip_ifindex(self) != ifindex) - return; - - if (!nm_device_is_real(self)) - return; - - if (nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT)) { - /* ignore all platform signals until the link is initialized in platform. */ - return; - } - - priv = NM_DEVICE_GET_PRIVATE(self); - - switch (obj_type) { - case NMP_OBJECT_TYPE_IP4_ADDRESS: - case NMP_OBJECT_TYPE_IP4_ROUTE: - if (!priv->queued_ip_config_id_4) { - priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self); - _LOGD(LOGD_DEVICE, "queued IP4 config change"); - } - break; - case NMP_OBJECT_TYPE_IP6_ADDRESS: - addr = platform_object; - - if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING - && nm_ndisc_dad_addr_is_fail_candidate_event(change_type, addr)) { - priv->dad6_failed_addrs = - g_slist_prepend(priv->dad6_failed_addrs, - (gpointer) nmp_object_ref(NMP_OBJECT_UP_CAST(addr))); - } - - /* fall-through */ - case NMP_OBJECT_TYPE_IP6_ROUTE: - if (!priv->queued_ip_config_id_6) { - priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self); - _LOGD(LOGD_DEVICE, "queued IP6 config change"); - } - break; - default: - g_return_if_reached(); - } -} - /*****************************************************************************/ NM_UTILS_FLAGS2STR_DEFINE(nm_unmanaged_flags2str, @@ -14956,7 +13959,7 @@ nm_device_get_unmanaged_flags(NMDevice *self, NMUnmanagedFlags flag) * Set the unmanaged flags of the device. **/ static void -_set_unmanaged_flags(NMDevice * self, +_set_unmanaged_flags(NMDevice *self, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, gboolean allow_state_transition, @@ -14967,7 +13970,7 @@ _set_unmanaged_flags(NMDevice * self, gboolean was_managed, transition_state; NMUnmanagedFlags old_flags, old_mask; NMDeviceState new_state; - const char * operation = NULL; + const char *operation = NULL; char str1[512]; char str2[512]; gboolean do_notify_has_pending_actions = FALSE; @@ -14995,12 +13998,6 @@ _set_unmanaged_flags(NMDevice * self, nm_device_set_unmanaged_flags(self, NM_UNMANAGED_USER_SETTINGS, !!unmanaged); } - /* trigger an initial update of IP configuration. */ - nm_assert_se(!nm_clear_g_source(&priv->queued_ip_config_id_4)); - nm_assert_se(!nm_clear_g_source(&priv->queued_ip_config_id_6)); - priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self); - priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self); - if (priv->pending_actions.len == 0) { do_notify_has_pending_actions = TRUE; had_pending_actions = nm_device_has_pending_action(self); @@ -15099,7 +14096,7 @@ nm_device_set_unmanaged_flags(NMDevice *self, NMUnmanagedFlags flags, NMUnmanFla * Set the unmanaged flags of the device and possibly trigger a state change. **/ void -nm_device_set_unmanaged_by_flags(NMDevice * self, +nm_device_set_unmanaged_by_flags(NMDevice *self, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, NMDeviceStateReason reason) @@ -15108,7 +14105,7 @@ nm_device_set_unmanaged_by_flags(NMDevice * self, } void -nm_device_set_unmanaged_by_flags_queue(NMDevice * self, +nm_device_set_unmanaged_by_flags_queue(NMDevice *self, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, NMDeviceStateReason reason) @@ -15143,7 +14140,7 @@ nm_device_check_unrealized_device_managed(NMDevice *self) } void -nm_device_set_unmanaged_by_user_settings(NMDevice *self) +nm_device_set_unmanaged_by_user_settings(NMDevice *self, gboolean now) { gboolean unmanaged; @@ -15165,11 +14162,13 @@ nm_device_set_unmanaged_by_user_settings(NMDevice *self) self, nm_settings_get_unmanaged_specs(NM_DEVICE_GET_PRIVATE(self)->settings)); - nm_device_set_unmanaged_by_flags(self, - NM_UNMANAGED_USER_SETTINGS, - !!unmanaged, - unmanaged ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED - : NM_DEVICE_STATE_REASON_NOW_MANAGED); + _set_unmanaged_flags(self, + NM_UNMANAGED_USER_SETTINGS, + !!unmanaged, + TRUE, + now, + unmanaged ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED + : NM_DEVICE_STATE_REASON_NOW_MANAGED); } void @@ -15247,12 +14246,12 @@ nm_device_set_unmanaged_by_quitting(NMDevice *self) void nm_device_reapply_settings_immediately(NMDevice *self) { - NMConnection * applied_connection; + NMConnection *applied_connection; NMSettingsConnection *settings_connection; NMDeviceState state; - NMSettingConnection * s_con_settings; - NMSettingConnection * s_con_applied; - const char * zone; + NMSettingConnection *s_con_settings; + NMSettingConnection *s_con_applied; + const char *zone; NMMetered metered; guint64 version_id; @@ -15322,10 +14321,10 @@ void nm_device_update_metered(NMDevice *self) { #define NM_METERED_INVALID ((NMMetered) -1) - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMSettingConnection *setting; NMMetered conn_value, value = NM_METERED_INVALID; - NMConnection * connection = NULL; + NMConnection *connection = NULL; NMDeviceState state; g_return_if_fail(NM_IS_DEVICE(self)); @@ -15352,9 +14351,13 @@ nm_device_update_metered(NMDevice *self) /* Try to guess a value using the metered flag in IP configuration */ if (value == NM_METERED_INVALID) { - if (priv->ip_config_4 && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE - && nm_ip4_config_get_metered(priv->ip_config_4)) - value = NM_METERED_GUESS_YES; + if (priv->l3cfg) { + const NML3ConfigData *l3cd; + + l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE); + if (l3cd && nm_l3_config_data_get_metered(l3cd) == NM_TERNARY_TRUE) + value = NM_METERED_GUESS_YES; + } } /* Otherwise, look at connection type. For Bluetooth, we look at the type of @@ -15400,14 +14403,14 @@ _device_check_dev_available_flags_from_con(NMDeviceCheckConAvailableFlags con_fl } static gboolean -_nm_device_check_connection_available(NMDevice * self, - NMConnection * connection, +_nm_device_check_connection_available(NMDevice *self, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { NMDeviceState state; - GError * local = NULL; + GError *local = NULL; /* an unrealized software device is always available, hardware devices never. */ if (!nm_device_is_real(self)) { @@ -15511,11 +14514,11 @@ _nm_device_check_connection_available(NMDevice * self, * Returns: %TRUE if @connection can be activated on @self */ gboolean -nm_device_check_connection_available(NMDevice * self, - NMConnection * connection, +nm_device_check_connection_available(NMDevice *self, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { gboolean available; @@ -15569,11 +14572,11 @@ available_connections_del(NMDevice *self, NMSettingsConnection *sett_conn) } static gboolean -check_connection_available(NMDevice * self, - NMConnection * connection, +check_connection_available(NMDevice *self, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -15616,12 +14619,12 @@ check_connection_available(NMDevice * self, void nm_device_recheck_available_connections(NMDevice *self) { - NMDevicePrivate * priv; - NMSettingsConnection *const *connections; - gboolean changed = FALSE; - GHashTableIter h_iter; - NMSettingsConnection * sett_conn; - guint i; + NMDevicePrivate *priv; + NMSettingsConnection *const *connections; + gboolean changed = FALSE; + GHashTableIter h_iter; + NMSettingsConnection *sett_conn; + guint i; gs_unref_hashtable GHashTable *prune_list = NULL; g_return_if_fail(NM_IS_DEVICE(self)); @@ -15678,7 +14681,7 @@ nm_device_recheck_available_connections(NMDevice *self) NMSettingsConnection * nm_device_get_best_connection(NMDevice *self, const char *specific_object, GError **error) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMSettingsConnection *sett_conn = NULL; NMSettingsConnection *candidate; guint64 best_timestamp = 0; @@ -15748,7 +14751,7 @@ cp_connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, gpoin } static void -cp_connection_updated(NMSettings * settings, +cp_connection_updated(NMSettings *settings, NMSettingsConnection *sett_conn, guint update_reason_u, gpointer user_data) @@ -15925,12 +14928,11 @@ _cancel_activation(NMDevice *self) priv->fw_state = FIREWALL_STATE_INITIALIZED; } - dispatcher_cleanup(self); + _dispatcher_cleanup(self); ip_check_gw_ping_cleanup(self); /* Break the activation chain */ - activation_source_clear(self, AF_INET); - activation_source_clear(self, AF_INET6); + activation_source_clear(self); } static void @@ -15960,17 +14962,13 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type) queued_state_clear(self); - nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release); - for (i = 0; i < 2; i++) nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free); - _cleanup_ip_pre(self, AF_INET, cleanup_type); - _cleanup_ip_pre(self, AF_INET6, cleanup_type); + _cleanup_ip_pre(self, AF_INET, cleanup_type, FALSE); + _cleanup_ip_pre(self, AF_INET6, cleanup_type, FALSE); - priv->ip_config_started = FALSE; - nm_clear_g_source_inst(&priv->ip_req_timeout_source_4); - nm_clear_g_source_inst(&priv->ip_req_timeout_source_6); + _dev_ip_state_req_timeout_cancel(self, AF_UNSPEC); } static void @@ -15978,54 +14976,16 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - priv->v4_commit_first_time = TRUE; - priv->v6_commit_first_time = TRUE; - priv->v4_route_table_initialized = FALSE; priv->v6_route_table_initialized = FALSE; + priv->l3config_merge_flags_has = FALSE; priv->v4_route_table_all_sync_before = FALSE; priv->v6_route_table_all_sync_before = FALSE; - priv->default_route_metric_penalty_ip4_has = FALSE; - priv->default_route_metric_penalty_ip6_has = FALSE; - - priv->linklocal6_dad_counter = 0; - priv->mtu_force_set_done = FALSE; - /* Clean up IP configs; this does not actually deconfigure the - * interface; the caller must flush routes and addresses explicitly. - */ - nm_device_set_ip_config(self, AF_INET, NULL, TRUE, NULL); - nm_device_set_ip_config(self, AF_INET6, NULL, TRUE, NULL); - g_clear_object(&priv->proxy_config); - g_clear_object(&priv->con_ip_config_4); - applied_config_clear(&priv->dev_ip_config_4); - applied_config_clear(&priv->dev2_ip_config_4); - g_clear_object(&priv->ext_ip_config_4); - g_clear_object(&priv->ip_config_4); - g_clear_object(&priv->con_ip_config_6); - applied_config_clear(&priv->ac_ip6_config); - g_clear_object(&priv->ext_ip_config_6); - g_clear_object(&priv->ext_ip6_config_captured); - applied_config_clear(&priv->dev2_ip_config_6); - g_clear_object(&priv->ip_config_6); - g_clear_object(&priv->dad6_ip6_config); - priv->ipv6ll_has = FALSE; - memset(&priv->ipv6ll_addr, 0, sizeof(priv->ipv6ll_addr)); - - nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref); - nm_clear_g_source(&priv->rt6_temporary_not_available_id); - - g_slist_free_full(priv->vpn_configs_4, g_object_unref); - priv->vpn_configs_4 = NULL; - g_slist_free_full(priv->vpn_configs_6, g_object_unref); - priv->vpn_configs_6 = NULL; - - /* We no longer accept the delegations. nm_device_set_ip_config(NULL) - * above disables them. */ - nm_assert(priv->needs_ip6_subnet == FALSE); + priv->needs_ip6_subnet = FALSE; if (priv->act_request.obj) { nm_active_connection_set_default(NM_ACTIVE_CONNECTION(priv->act_request.obj), @@ -16047,6 +15007,9 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type) * or ATM device). */ _set_ip_ifindex(self, 0, NULL); + + nm_clear_g_source_inst(&priv->ip_data_4.check_async_source); + nm_clear_g_source_inst(&priv->ip_data_6.check_async_source); } /* @@ -16078,7 +15041,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu /* Turn off kernel IPv6 */ if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) { - set_disable_ipv6(self, "1"); + _dev_sysctl_set_disable_ipv6(self, TRUE); nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0"); } @@ -16094,12 +15057,10 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu /* Take out any entries in the routing table and any IP address the device had. */ if (ifindex > 0) { - NMPlatform * platform = nm_device_get_platform(self); - NMUtilsIPv6IfaceId iid = {}; + NMPlatform *platform = nm_device_get_platform(self); nm_platform_ip_route_flush(platform, AF_UNSPEC, ifindex); nm_platform_ip_address_flush(platform, AF_UNSPEC, ifindex); - set_ipv6_token(self, &iid, "::"); if (nm_device_get_applied_setting(self, NM_TYPE_SETTING_TC_CONFIG)) { nm_platform_tc_sync(platform, ifindex, NULL, NULL); @@ -16192,213 +15153,13 @@ deactivate_reset_hw_addr(NMDevice *self) nm_device_hw_addr_reset(self, "deactivate"); } -static char * -find_dhcp4_address(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - const NMPlatformIP4Address *a; - NMDedupMultiIter ipconf_iter; - - if (!priv->ip_config_4) - return NULL; - - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip_config_4, &a) { - if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP) - return nm_utils_inet4_ntop_dup(a->address); - } - return NULL; -} - -void -nm_device_spawn_iface_helper(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - gboolean configured = FALSE; - NMConnection * connection; - GError * error = NULL; - const char * method; - GPtrArray * argv; - gs_free char * dhcp4_address = NULL; - char * logging_backend; - NMUtilsStableType stable_type; - const char * stable_id; - - if (priv->state != NM_DEVICE_STATE_ACTIVATED) - return; - if (!nm_device_can_assume_connections(self)) - return; - - connection = nm_device_get_applied_connection(self); - - g_return_if_fail(connection); - - argv = g_ptr_array_sized_new(10); - g_ptr_array_set_free_func(argv, g_free); - - g_ptr_array_add(argv, g_strdup(LIBEXECDIR "/nm-iface-helper")); - g_ptr_array_add(argv, g_strdup("--ifname")); - g_ptr_array_add(argv, g_strdup(nm_device_get_ip_iface(self))); - g_ptr_array_add(argv, g_strdup("--uuid")); - g_ptr_array_add(argv, g_strdup(nm_connection_get_uuid(connection))); - - stable_id = _prop_get_connection_stable_id(self, connection, &stable_type); - if (stable_type != NM_UTILS_STABLE_TYPE_UUID) { - g_ptr_array_add(argv, g_strdup("--stable-id")); - g_ptr_array_add(argv, g_strdup_printf("%d %s", (int) stable_type, stable_id)); - } - - logging_backend = - nm_config_data_get_value(NM_CONFIG_GET_DATA_ORIG, - NM_CONFIG_KEYFILE_GROUP_LOGGING, - NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND, - NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); - if (logging_backend) { - g_ptr_array_add(argv, g_strdup("--logging-backend")); - g_ptr_array_add(argv, logging_backend); - } - - g_ptr_array_add(argv, g_strdup("--log-level")); - g_ptr_array_add(argv, g_strdup(nm_logging_level_to_string())); - - g_ptr_array_add(argv, g_strdup("--log-domains")); - g_ptr_array_add(argv, g_strdup(nm_logging_domains_to_string())); - - dhcp4_address = find_dhcp4_address(self); - - method = nm_device_get_effective_ip_config_method(self, AF_INET); - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { - NMSettingIPConfig *s_ip4; - - s_ip4 = nm_connection_get_setting_ip4_config(connection); - nm_assert(s_ip4); - - g_ptr_array_add(argv, g_strdup("--priority4")); - g_ptr_array_add(argv, g_strdup_printf("%u", nm_device_get_route_metric(self, AF_INET))); - - g_ptr_array_add(argv, g_strdup("--dhcp4")); - g_ptr_array_add(argv, g_strdup(dhcp4_address)); - if (nm_setting_ip_config_get_may_fail(s_ip4) == FALSE) - g_ptr_array_add(argv, g_strdup("--dhcp4-required")); - - if (priv->dhcp_data_4.client) { - const char *hostname; - GBytes * client_id; - - client_id = nm_dhcp_client_get_client_id(priv->dhcp_data_4.client); - if (client_id) { - g_ptr_array_add(argv, g_strdup("--dhcp4-clientid")); - g_ptr_array_add(argv, - nm_utils_bin2hexstr_full(g_bytes_get_data(client_id, NULL), - g_bytes_get_size(client_id), - ':', - FALSE, - NULL)); - } - - hostname = nm_dhcp_client_get_hostname(priv->dhcp_data_4.client); - if (hostname) { - if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(priv->dhcp_data_4.client), - NM_DHCP_CLIENT_FLAGS_USE_FQDN)) - g_ptr_array_add(argv, g_strdup("--dhcp4-fqdn")); - else - g_ptr_array_add(argv, g_strdup("--dhcp4-hostname")); - g_ptr_array_add(argv, g_strdup(hostname)); - } - } - - configured = TRUE; - } - - method = nm_utils_get_ip_config_method(connection, AF_INET6); - if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { - NMSettingIPConfig *s_ip6; - NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT; - - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - - g_ptr_array_add(argv, g_strdup("--priority6")); - g_ptr_array_add(argv, g_strdup_printf("%u", nm_device_get_route_metric(self, AF_INET6))); - - g_ptr_array_add(argv, g_strdup("--slaac")); - - if (nm_setting_ip_config_get_may_fail(s_ip6) == FALSE) - g_ptr_array_add(argv, g_strdup("--slaac-required")); - - g_ptr_array_add(argv, g_strdup("--slaac-tempaddr")); - g_ptr_array_add(argv, g_strdup_printf("%d", priv->ndisc_use_tempaddr)); - - if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) { - g_ptr_array_add(argv, g_strdup("--iid")); - g_ptr_array_add( - argv, - nm_utils_bin2hexstr_full(iid.id_u8, sizeof(NMUtilsIPv6IfaceId), ':', FALSE, NULL)); - } - - g_ptr_array_add(argv, g_strdup("--addr-gen-mode")); - g_ptr_array_add( - argv, - g_strdup_printf("%d", - nm_setting_ip6_config_get_addr_gen_mode(NM_SETTING_IP6_CONFIG(s_ip6)))); - - configured = TRUE; - } - - if (configured) { - GPid pid; - - g_ptr_array_add(argv, NULL); - - if (nm_logging_enabled(LOGL_DEBUG, LOGD_DEVICE)) { - char *tmp; - - tmp = g_strjoinv(" ", (char **) argv->pdata); - _LOGD(LOGD_DEVICE, "running '%s'", tmp); - g_free(tmp); - } - - if (g_spawn_async(NULL, - (char **) argv->pdata, - NULL, - G_SPAWN_DO_NOT_REAP_CHILD, - NULL, - NULL, - &pid, - &error)) { - _LOGI(LOGD_DEVICE, "spawned helper PID %u", (guint) pid); - } else { - _LOGW(LOGD_DEVICE, "failed to spawn helper: %s", error->message); - g_error_free(error); - } - } - - g_ptr_array_unref(argv); -} - /*****************************************************************************/ -static gboolean -ip_config_valid(NMDeviceState state) -{ - return (state == NM_DEVICE_STATE_UNMANAGED) - || (state >= NM_DEVICE_STATE_IP_CHECK && state <= NM_DEVICE_STATE_DEACTIVATING); -} - -static void -notify_ip_properties(NMDevice *self) -{ - _notify(self, PROP_IP_IFACE); - _notify(self, PROP_IP4_CONFIG); - _notify(self, PROP_DHCP4_CONFIG); - _notify(self, PROP_IP6_CONFIG); - _notify(self, PROP_DHCP6_CONFIG); -} - static void ip6_managed_setup(NMDevice *self) { - set_nm_ipv6ll(self, TRUE); - set_disable_ipv6(self, "1"); + _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE); + _dev_sysctl_set_disable_ipv6(self, FALSE); nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "0"); nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0"); nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "0"); @@ -16422,7 +15183,7 @@ deactivate_ready(NMDevice *self, NMDeviceStateReason reason) static void sriov_reset_on_deactivate_cb(GError *error, gpointer user_data) { - NMDevice * self; + NMDevice *self; NMDevicePrivate *priv; gpointer reason; @@ -16440,7 +15201,7 @@ sriov_reset_on_deactivate_cb(GError *error, gpointer user_data) static void sriov_reset_on_failure_cb(GError *error, gpointer user_data) { - NMDevice * self = user_data; + NMDevice *self = user_data; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); nm_assert(priv->sriov_reset_pending > 0); @@ -16457,7 +15218,7 @@ sriov_reset_on_failure_cb(GError *error, gpointer user_data) static void deactivate_async_ready(NMDevice *self, GError *error, gpointer user_data) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceStateReason reason = GPOINTER_TO_UINT(user_data); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { @@ -16478,8 +15239,8 @@ deactivate_async_ready(NMDevice *self, GError *error, gpointer user_data) static void deactivate_dispatcher_complete(NMDispatcherCallId *call_id, gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevice *self = NM_DEVICE(user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceStateReason reason; g_return_if_fail(call_id == priv->dispatcher.call_id); @@ -16532,20 +15293,19 @@ deactivate_dispatcher_complete(NMDispatcherCallId *call_id, gpointer user_data) static void _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gboolean quitting) { - NMDevicePrivate *priv; - NMDeviceState old_state; - gs_unref_object NMActRequest *req = NULL; + gs_unref_object NMActRequest *req = NULL; + NMDevicePrivate *priv; + NMDeviceState old_state; gboolean no_firmware = FALSE; - NMSettingsConnection * sett_conn; - NMSettingSriov * s_sriov; + NMSettingsConnection *sett_conn; + NMSettingSriov *s_sriov; gboolean concheck_now; g_return_if_fail(NM_IS_DEVICE(self)); priv = NM_DEVICE_GET_PRIVATE(self); - /* Track re-entry */ - g_warn_if_fail(priv->in_state_changed == FALSE); + g_return_if_fail(priv->in_state_changed == 0); old_state = priv->state; @@ -16582,14 +15342,14 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, * by the device not having any pending action anymore * we add one here that gets removed at the end of the function */ nm_device_add_pending_action(self, NM_PENDING_ACTION_IN_STATE_CHANGE, TRUE); - priv->in_state_changed = TRUE; + priv->in_state_changed++; priv->state = state; priv->state_reason = reason; queued_state_clear(self); - dispatcher_cleanup(self); + _dispatcher_cleanup(self); nm_clear_g_cancellable(&priv->deactivating_cancellable); @@ -16646,15 +15406,15 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, nm_device_cleanup(self, reason, CLEANUP_TYPE_DECONFIGURE); nm_device_take_down(self, TRUE); nm_device_hw_addr_reset(self, "unmanage"); - set_nm_ipv6ll(self, FALSE); - restore_ip6_properties(self); + _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_EUI64); + _dev_sysctl_restore_ip6_properties(self); } } nm_device_sys_iface_state_set(self, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); break; case NM_DEVICE_STATE_UNAVAILABLE: if (old_state == NM_DEVICE_STATE_UNMANAGED) { - save_ip6_properties(self); + _dev_sysctl_save_ip6_properties(self); if (priv->sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_MANAGED) ip6_managed_setup(self); device_init_static_sriov_num_vfs(self); @@ -16683,7 +15443,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, /* Ensure devices that previously assumed a connection now have * userspace IPv6LL enabled. */ - set_nm_ipv6ll(self, TRUE); + _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE); nm_device_cleanup(self, reason, CLEANUP_TYPE_DECONFIGURE); } else if (old_state < NM_DEVICE_STATE_DISCONNECTED) { @@ -16703,8 +15463,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, /* Clean up any half-done IP operations if the device's layer2 * finds out it needs authentication during IP config. */ - _cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_DECONFIGURE); - _cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_DECONFIGURE, FALSE); + _cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_DECONFIGURE, FALSE); } break; default: @@ -16796,9 +15556,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, _LOGI(LOGD_DEVICE, "Activation: successful, device activated."); nm_device_update_metered(self); nm_dispatcher_call_device(NM_DISPATCHER_ACTION_UP, self, req, NULL, NULL, NULL); - - if (priv->proxy_config) - _pacrunner_manager_add(self); + _pacrunner_manager_add(self); break; case NM_DEVICE_STATE_FAILED: /* Usually upon failure the activation chain is interrupted in @@ -16859,10 +15617,6 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, } else nm_device_start_ip_check(self); - /* IP-related properties are only valid when the device has IP configuration; - * now that it does, ensure their change notifications are emitted. - */ - notify_ip_properties(self); break; } case NM_DEVICE_STATE_SECONDARIES: @@ -16885,18 +15639,15 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, } } - /* IP-related properties are only valid when the device has IP configuration. - * If it no longer does, ensure their change notifications are emitted. - */ - if (ip_config_valid(old_state) && !ip_config_valid(state)) - notify_ip_properties(self); - concheck_now = NM_IN_SET(state, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_DISCONNECTED) || old_state >= NM_DEVICE_STATE_ACTIVATED; concheck_update_interval(self, AF_INET, concheck_now); concheck_update_interval(self, AF_INET6, concheck_now); - priv->in_state_changed = FALSE; + update_prop_ip_iface(self); + + priv->in_state_changed--; + nm_device_remove_pending_action(self, NM_PENDING_ACTION_IN_STATE_CHANGE, TRUE); if ((old_state > NM_DEVICE_STATE_UNMANAGED) != (state > NM_DEVICE_STATE_UNMANAGED)) @@ -16912,8 +15663,8 @@ nm_device_state_changed(NMDevice *self, NMDeviceState state, NMDeviceStateReason static gboolean queued_state_set(gpointer user_data) { - NMDevice * self = NM_DEVICE(user_data); - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevice *self = NM_DEVICE(user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDeviceState new_state; NMDeviceStateReason new_reason; @@ -17048,7 +15799,7 @@ gboolean nm_device_update_hw_address(NMDevice *self) { NMDevicePrivate *priv; - const guint8 * hwaddr; + const guint8 *hwaddr; gsize hwaddrlen = 0; priv = NM_DEVICE_GET_PRIVATE(self); @@ -17123,11 +15874,11 @@ nm_device_update_initial_hw_address(NMDevice *self) void nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); guint8 buf[_NM_UTILS_HWADDR_LEN_MAX]; gboolean success_read; int ifindex; - const NMPlatformLink * pllink; + const NMPlatformLink *pllink; const NMConfigDeviceStateData *dev_state; NMPLinkAddress cached_hw_addr_perm; @@ -17236,7 +15987,7 @@ _hw_addr_matches(NMDevice *self, const guint8 *addr, gsize addr_len) } static gboolean -_hw_addr_set(NMDevice * self, +_hw_addr_set(NMDevice *self, const char *const addr, const char *const operation, const char *const detail) @@ -17439,20 +16190,20 @@ nm_device_hw_addr_set(NMDevice *self, const char *addr, const char *detail, gboo * %TRUE otherwise */ static gboolean -_hw_addr_get_cloned(NMDevice * self, +_hw_addr_get_cloned(NMDevice *self, NMConnection *connection, gboolean is_wifi, - gboolean * preserve, - char ** hwaddr, - HwAddrType * hwaddr_type, - const char ** hwaddr_detail, - GError ** error) + gboolean *preserve, + char **hwaddr, + HwAddrType *hwaddr_type, + const char **hwaddr_detail, + GError **error) { NMDevicePrivate *priv; - gs_free char * hw_addr_generated = NULL; - const char * addr; - const char * addr_setting; - char * addr_out; + gs_free char *hw_addr_generated = NULL; + const char *addr; + const char *addr_setting; + char *addr_out; HwAddrType type_out; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); @@ -17520,7 +16271,7 @@ _hw_addr_get_cloned(NMDevice * self, type_out = HW_ADDR_TYPE_GENERATED; } else if (NM_IN_STRSET(addr, NM_CLONED_MAC_STABLE)) { NMUtilsStableType stable_type; - const char * stable_id; + const char *stable_id; if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) { /* hm, we already use a generate MAC address. Most certainly, that is from the same @@ -17569,12 +16320,12 @@ out_no_action: } gboolean -nm_device_hw_addr_get_cloned(NMDevice * self, +nm_device_hw_addr_get_cloned(NMDevice *self, NMConnection *connection, gboolean is_wifi, - char ** hwaddr, - gboolean * preserve, - GError ** error) + char **hwaddr, + gboolean *preserve, + GError **error) { if (!_hw_addr_get_cloned(self, connection, is_wifi, preserve, hwaddr, NULL, NULL, error)) return FALSE; @@ -17585,12 +16336,12 @@ nm_device_hw_addr_get_cloned(NMDevice * self, gboolean nm_device_hw_addr_set_cloned(NMDevice *self, NMConnection *connection, gboolean is_wifi) { - NMDevicePrivate *priv; - gboolean preserve = FALSE; - gs_free char * hwaddr = NULL; - const char * detail = NULL; - HwAddrType type = HW_ADDR_TYPE_UNSET; - gs_free_error GError *error = NULL; + NMDevicePrivate *priv; + gboolean preserve = FALSE; + gs_free char *hwaddr = NULL; + const char *detail = NULL; + HwAddrType type = HW_ADDR_TYPE_UNSET; + gs_free_error GError *error = NULL; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); priv = NM_DEVICE_GET_PRIVATE(self); @@ -17622,7 +16373,7 @@ gboolean nm_device_hw_addr_reset(NMDevice *self, const char *detail) { NMDevicePrivate *priv; - const char * addr; + const char *addr; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); @@ -17711,9 +16462,9 @@ nm_device_spec_match_list(NMDevice *self, const GSList *specs) int nm_device_spec_match_list_full(NMDevice *self, const GSList *specs, int no_match_value) { - NMDeviceClass * klass; + NMDeviceClass *klass; NMMatchSpecMatchType m; - const char * hw_address = NULL; + const char *hw_address = NULL; gboolean is_fake; g_return_val_if_fail(NM_IS_DEVICE(self), FALSE); @@ -17748,7 +16499,7 @@ nm_device_spec_match_list_full(NMDevice *self, const GSList *specs, int no_match guint nm_device_get_supplicant_timeout(NMDevice *self) { - NMConnection * connection; + NMConnection *connection; NMSetting8021x *s_8021x; int timeout; #define SUPPLICANT_DEFAULT_TIMEOUT 25 @@ -17777,7 +16528,7 @@ nm_device_get_supplicant_timeout(NMDevice *self) gboolean nm_device_auth_retries_try_next(NMDevice *self) { - NMDevicePrivate * priv; + NMDevicePrivate *priv; NMSettingConnection *s_con; int auth_retries; @@ -17826,11 +16577,11 @@ nm_device_auth_retries_try_next(NMDevice *self) static void hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer user_data) { - HostnameResolver *resolver; - NMDevice * self; - gs_free char * addr_str = NULL; - gs_free char * output = NULL; - gs_free_error GError *error = NULL; + HostnameResolver *resolver; + NMDevice *self; + gs_free char *addr_str = NULL; + gs_free char *output = NULL; + gs_free_error GError *error = NULL; output = nm_device_resolve_address_finish(result, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -17869,7 +16620,7 @@ static gboolean hostname_dns_address_timeout(gpointer user_data) { HostnameResolver *resolver = user_data; - NMDevice * self = resolver->device; + NMDevice *self = resolver->device; g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE); @@ -17914,17 +16665,70 @@ nm_device_clear_dns_lookup_data(NMDevice *self) nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free); } +static GInetAddress * +get_address_for_hostname_dns_lookup(NMDevice *self, int addr_family) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMPLookup lookup; + const NMDedupMultiHeadEntry *head_entry; + const NMDedupMultiEntry *iter; + const guint8 *addr6_ll = NULL; + const guint8 *addr6_nonll = NULL; + int ifindex; + + ifindex = nm_device_get_ip_ifindex(self); + if (ifindex <= 0) + return NULL; + + /* FIXME(l3cfg): now we lookup the address from platform. Should we instead look + * it up from NML3Cfg? That is, take an address that we want to configure as + * opposed to an address that is configured? */ + head_entry = nm_platform_lookup( + nm_device_get_platform(self), + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex)); + + if (head_entry) { + c_list_for_each_entry (iter, &head_entry->lst_entries_head, lst_entries) { + const NMPlatformIPAddress *addr = NMP_OBJECT_CAST_IP_ADDRESS(iter->obj); + + if (IS_IPv4) { + return g_inet_address_new_from_bytes(addr->address_ptr, G_SOCKET_FAMILY_IPV4); + } + + /* For IPv6 prefer, in order: + * - !link-local, !deprecated + * - !link-local, deprecated + * - link-local + */ + + if (!IN6_IS_ADDR_LINKLOCAL(addr->address_ptr)) { + if (!(addr->n_ifa_flags & IFA_F_DEPRECATED)) { + return g_inet_address_new_from_bytes(addr->address_ptr, G_SOCKET_FAMILY_IPV6); + } + addr6_nonll = addr->address_ptr; + continue; + } + + addr6_ll = addr->address_ptr; + } + + if (addr6_nonll || addr6_ll) + return g_inet_address_new_from_bytes(addr6_nonll ?: addr6_ll, G_SOCKET_FAMILY_IPV6); + } + + return NULL; +} + /* return value is valid only immediately */ const char * nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_wait) { - NMDevicePrivate * priv; - const int IS_IPv4 = NM_IS_IPv4(addr_family); - HostnameResolver *resolver; - NMIPConfig * ip_config; - const char * method; - gboolean address_changed = FALSE; - gs_unref_object GInetAddress *new_address = NULL; + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv; + HostnameResolver *resolver; + const char *method; + gboolean address_changed = FALSE; + gs_unref_object GInetAddress *new_address = NULL; g_return_val_if_fail(NM_IS_DEVICE(self), NULL); priv = NM_DEVICE_GET_PRIVATE(self); @@ -17966,41 +16770,7 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean /* Determine the most suitable address of the interface * and whether it changed from the previous lookup */ - ip_config = priv->ip_config_x[IS_IPv4]; - if (ip_config) { - const NMPlatformIPAddress *addr = NULL; - - if (IS_IPv4) { - addr = nm_ip_config_get_first_address(ip_config); - } else { - /* For IPv6 prefer, in order: - * - !link-local, !deprecated - * - !link-local, deprecated - * - link-local - */ - addr = nm_ip_config_find_first_address(ip_config, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL); - if (!addr) { - addr = nm_ip_config_find_first_address( - ip_config, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED); - } - if (!addr) { - addr = nm_ip_config_find_first_address(ip_config, - NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL - | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY); - } - } - - if (addr) { - new_address = g_inet_address_new_from_bytes(addr->address_ptr, - IS_IPv4 ? G_SOCKET_FAMILY_IPV4 - : G_SOCKET_FAMILY_IPV6); - } - } - + new_address = get_address_for_hostname_dns_lookup(self, addr_family); if (new_address && resolver->address) { if (!g_inet_address_equal(new_address, resolver->address)) address_changed = TRUE; @@ -18072,11 +16842,7 @@ _activation_func_to_string(ActivationHandleFunc func) G_STMT_END FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage1_device_prepare); FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage2_device_config); - FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage3_ip_config_start); - FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage4_ip_config_timeout_4); - FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage4_ip_config_timeout_6); - FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage5_ip_config_result_4); - FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage5_ip_config_result_6); + FUNC_TO_STRING_CHECK_AND_RETURN(func, activate_stage3_ip_config); g_return_val_if_reached("unknown"); } @@ -18084,7 +16850,7 @@ static GVariant * _device_get_ports_variant(NMDevice *device) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(device); - SlaveInfo * info; + SlaveInfo *info; GVariantBuilder builder; gboolean any = FALSE; @@ -18116,7 +16882,7 @@ _device_get_ports_variant(NMDevice *device) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDevice * self = NM_DEVICE(object); + NMDevice *self = NM_DEVICE(object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); switch (prop_id) { @@ -18139,13 +16905,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) nm_utils_str_utf8safe_escape_cp(priv->iface, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)); break; case PROP_IP_IFACE: - if (ip_config_valid(priv->state)) { - g_value_take_string( - value, - nm_utils_str_utf8safe_escape_cp(nm_device_get_ip_iface(self), - NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)); - } else - g_value_set_string(value, NULL); + g_value_set_string(value, priv->prop_ip_iface); break; case PROP_IFINDEX: g_value_set_int(value, priv->ifindex); @@ -18180,24 +16940,16 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_value_set_uint(value, priv->mtu); break; case PROP_IP4_CONFIG: - nm_dbus_utils_g_value_set_object_path(value, - ip_config_valid(priv->state) ? priv->ip_config_4 - : NULL); + nm_dbus_utils_g_value_set_object_path(value, priv->l3ipdata_4.ip_config); break; case PROP_DHCP4_CONFIG: - nm_dbus_utils_g_value_set_object_path( - value, - ip_config_valid(priv->state) ? priv->dhcp_data_4.config : NULL); + nm_dbus_utils_g_value_set_object_path(value, priv->ipdhcp_data_4.config); break; case PROP_IP6_CONFIG: - nm_dbus_utils_g_value_set_object_path(value, - ip_config_valid(priv->state) ? priv->ip_config_6 - : NULL); + nm_dbus_utils_g_value_set_object_path(value, priv->l3ipdata_6.ip_config); break; case PROP_DHCP6_CONFIG: - nm_dbus_utils_g_value_set_object_path( - value, - ip_config_valid(priv->state) ? priv->dhcp_data_6.config : NULL); + nm_dbus_utils_g_value_set_object_path(value, priv->ipdhcp_data_6.config); break; case PROP_STATE: g_value_set_uint(value, priv->state); @@ -18307,7 +17059,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDevice * self = (NMDevice *) object; + NMDevice *self = (NMDevice *) object; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); switch (prop_id) { @@ -18404,6 +17156,8 @@ nm_device_init(NMDevice *self) c_list_init(&self->devices_lst); c_list_init(&priv->slaves); + priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE; + priv->concheck_x[0].state = NM_CONNECTIVITY_UNKNOWN; priv->concheck_x[1].state = NM_CONNECTIVITY_UNKNOWN; @@ -18429,19 +17183,16 @@ nm_device_init(NMDevice *self) priv->ip6_saved_properties = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, g_free); priv->sys_iface_state_ = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; - priv->v4_commit_first_time = TRUE; - priv->v6_commit_first_time = TRUE; - priv->promisc_reset = NM_OPTION_BOOL_DEFAULT; } static GObject * constructor(GType type, guint n_construct_params, GObjectConstructParam *construct_params) { - GObject * object; - GObjectClass * klass; - NMDevice * self; - NMDevicePrivate * priv; + GObject *object; + GObjectClass *klass; + NMDevice *self; + NMDevicePrivate *priv; const NMPlatformLink *pllink; klass = G_OBJECT_CLASS(nm_device_parent_class); @@ -18481,31 +17232,14 @@ constructor(GType type, guint n_construct_params, GObjectConstructParam *constru static void constructed(GObject *object) { - NMDevice * self = NM_DEVICE(object); + NMDevice *self = NM_DEVICE(object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMPlatform * platform; + NMPlatform *platform; if (NM_DEVICE_GET_CLASS(self)->get_generic_capabilities) priv->capabilities |= NM_DEVICE_GET_CLASS(self)->get_generic_capabilities(self); - /* Watch for external IP config changes */ platform = nm_device_get_platform(self); - g_signal_connect(platform, - NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, - G_CALLBACK(device_ipx_changed), - self); - g_signal_connect(platform, - NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, - G_CALLBACK(device_ipx_changed), - self); - g_signal_connect(platform, - NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, - G_CALLBACK(device_ipx_changed), - self); - g_signal_connect(platform, - NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, - G_CALLBACK(device_ipx_changed), - self); g_signal_connect(platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK(link_changed_cb), self); priv->manager = g_object_ref(NM_MANAGER_GET); @@ -18532,11 +17266,11 @@ constructed(GObject *object) static void dispose(GObject *object) { - NMDevice * self = NM_DEVICE(object); - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMPlatform * platform; + NMDevice *self = NM_DEVICE(object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + NMPlatform *platform; NMDeviceConnectivityHandle *con_handle; - gs_free_error GError *cancelled_error = NULL; + gs_free_error GError *cancelled_error = NULL; _LOGD(LOGD_DEVICE, "disposing"); @@ -18557,15 +17291,12 @@ dispose(GObject *object) _parent_set_ifindex(self, 0, FALSE); platform = nm_device_get_platform(self); - g_signal_handlers_disconnect_by_func(platform, G_CALLBACK(device_ipx_changed), self); g_signal_handlers_disconnect_by_func(platform, G_CALLBACK(link_changed_cb), self); - arp_cleanup(self); - nm_clear_g_signal_handler(nm_config_get(), &priv->config_changed_id); nm_clear_g_signal_handler(priv->manager, &priv->ifindex_changed_id); - dispatcher_cleanup(self); + _dispatcher_cleanup(self); nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id); @@ -18574,7 +17305,7 @@ dispose(GObject *object) nm_assert(c_list_is_empty(&priv->slaves)); /* Let the kernel manage IPv6LL again */ - set_nm_ipv6ll(self, FALSE); + _dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_EUI64); _cleanup_generic_post(self, CLEANUP_TYPE_KEEP); @@ -18621,6 +17352,10 @@ dispose(GObject *object) priv->sriov.next = NULL; } + g_clear_object(&priv->l3cfg); + g_clear_object(&priv->l3ipdata_4.ip_config); + g_clear_object(&priv->l3ipdata_6.ip_config); + G_OBJECT_CLASS(nm_device_parent_class)->dispose(object); if (nm_clear_g_source(&priv->queued_state.id)) { @@ -18634,7 +17369,7 @@ dispose(GObject *object) static void finalize(GObject *object) { - NMDevice * self = NM_DEVICE(object); + NMDevice *self = NM_DEVICE(object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); _LOGD(LOGD_DEVICE, "finalize(): %s", G_OBJECT_TYPE_NAME(self)); @@ -18643,7 +17378,6 @@ finalize(GObject *object) g_free(priv->hw_addr_perm); g_free(priv->hw_addr_initial); g_free(priv->pending_actions.arr); - g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); nm_clear_g_free(&priv->physical_port_id); g_free(priv->udi); g_free(priv->path); @@ -18806,7 +17540,7 @@ static const NMDBusInterfaceInfoExtended interface_info_device_statistics = { static void nm_device_class_init(NMDeviceClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); g_type_class_add_private(object_class, sizeof(NMDevicePrivate)); @@ -18824,10 +17558,9 @@ nm_device_class_init(NMDeviceClass *klass) klass->link_changed = link_changed; - klass->is_available = is_available; - klass->act_stage2_config = act_stage2_config; - klass->act_stage3_ip_config_start = act_stage3_ip_config_start; - klass->act_stage4_ip_config_timeout = act_stage4_ip_config_timeout; + klass->is_available = is_available; + klass->act_stage2_config = act_stage2_config; + klass->get_ip_method_auto = get_ip_method_auto; klass->get_type_description = get_type_description; klass->can_auto_connect = can_auto_connect; @@ -19166,29 +17899,17 @@ nm_device_class_init(NMDeviceClass *klass) G_TYPE_BOOLEAN, 0); - signals[IP4_CONFIG_CHANGED] = g_signal_new(NM_DEVICE_IP4_CONFIG_CHANGED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 2, - G_TYPE_OBJECT, - G_TYPE_OBJECT); - - signals[IP6_CONFIG_CHANGED] = g_signal_new(NM_DEVICE_IP6_CONFIG_CHANGED, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 2, - G_TYPE_OBJECT, - G_TYPE_OBJECT); + signals[L3CD_CHANGED] = g_signal_new(NM_DEVICE_L3CD_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_POINTER, /* (const NML3ConfigData *l3cd_old) */ + G_TYPE_POINTER /* (const NML3ConfigData *l3cd_new) */); signals[IP6_PREFIX_DELEGATED] = g_signal_new(NM_DEVICE_IP6_PREFIX_DELEGATED, @@ -19251,6 +17972,16 @@ nm_device_class_init(NMDeviceClass *klass) NULL, G_TYPE_NONE, 0); + + signals[PLATFORM_ADDRESS_CHANGED] = g_signal_new(NM_DEVICE_PLATFORM_ADDRESS_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); } /* Connection defaults from plugins */ diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index d967bcb2..cfcd4ade 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -9,13 +9,14 @@ #include <netinet/in.h> -#include "nm-setting-connection.h" -#include "nm-dbus-object.h" -#include "nm-dbus-interface.h" -#include "nm-connection.h" -#include "nm-rfkill-manager.h" #include "NetworkManagerUtils.h" +#include "nm-connection.h" +#include "nm-dbus-interface.h" +#include "nm-dbus-object.h" #include "nm-device-utils.h" +#include "nm-l3cfg.h" +#include "nm-rfkill-manager.h" +#include "nm-setting-connection.h" /* Properties */ #define NM_DEVICE_UDI "udi" @@ -70,17 +71,17 @@ #define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */ /* Internal signals */ -#define NM_DEVICE_DNS_LOOKUP_DONE "dns-lookup-done" -#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed" -#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed" -#define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated" -#define NM_DEVICE_IP6_SUBNET_NEEDED "ip6-subnet-needed" -#define NM_DEVICE_REMOVED "removed" -#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate" -#define NM_DEVICE_RECHECK_ASSUME "recheck-assume" -#define NM_DEVICE_STATE_CHANGED "state-changed" -#define NM_DEVICE_LINK_INITIALIZED "link-initialized" -#define NM_DEVICE_AUTOCONNECT_ALLOWED "autoconnect-allowed" +#define NM_DEVICE_DNS_LOOKUP_DONE "dns-lookup-done" +#define NM_DEVICE_L3CD_CHANGED "l3cd-changed" +#define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated" +#define NM_DEVICE_IP6_SUBNET_NEEDED "ip6-subnet-needed" +#define NM_DEVICE_REMOVED "removed" +#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate" +#define NM_DEVICE_RECHECK_ASSUME "recheck-assume" +#define NM_DEVICE_STATE_CHANGED "state-changed" +#define NM_DEVICE_LINK_INITIALIZED "link-initialized" +#define NM_DEVICE_AUTOCONNECT_ALLOWED "autoconnect-allowed" +#define NM_DEVICE_PLATFORM_ADDRESS_CHANGED "platform-address-changed" #define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms" #define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes" @@ -169,7 +170,7 @@ typedef struct _NMDeviceClass { NMDBusObjectClass parent; struct _NMDeviceClass *default_type_description_klass; - const char * default_type_description; + const char *default_type_description; const char *connection_type_supported; @@ -208,7 +209,7 @@ typedef struct _NMDeviceClass { bool can_reapply_change_ovs_external_ids : 1; - void (*state_changed)(NMDevice * device, + void (*state_changed)(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason); @@ -232,11 +233,11 @@ typedef struct _NMDeviceClass { * * Returns: %TRUE on success, %FALSE on error */ - gboolean (*create_and_realize)(NMDevice * self, - NMConnection * connection, - NMDevice * parent, + gboolean (*create_and_realize)(NMDevice *self, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error); + GError **error); /** * realize_start_notify(): @@ -294,13 +295,13 @@ typedef struct _NMDeviceClass { * which emits NM_DEVICE_RECHECK_AUTO_ACTIVATE signal. */ gboolean (*get_autoconnect_allowed)(NMDevice *self); - gboolean (*can_auto_connect)(NMDevice * self, + gboolean (*can_auto_connect)(NMDevice *self, NMSettingsConnection *sett_conn, - char ** specific_object); + char **specific_object); - guint32 (*get_configured_mtu)(NMDevice * self, + guint32 (*get_configured_mtu)(NMDevice *self, NMDeviceMtuSource *out_source, - gboolean * out_force); + gboolean *out_force); /* allow the subclass to overwrite the routing table. This is mainly useful * to change from partial mode (route-table=0) to full-sync mode (route-table=254). */ @@ -315,9 +316,9 @@ typedef struct _NMDeviceClass { * only the devices type and characteristics. Does not use any live * network information like Wi-Fi scan lists etc. */ - gboolean (*check_connection_compatible)(NMDevice * self, + gboolean (*check_connection_compatible)(NMDevice *self, NMConnection *connection, - GError ** error); + GError **error); /* Checks whether the connection is likely available to be activated, * including any live network information like scan lists. The connection @@ -330,33 +331,28 @@ typedef struct _NMDeviceClass { * * Specifying @specific_object can only reduce the availability of a connection. */ - gboolean (*check_connection_available)(NMDevice * self, - NMConnection * connection, + gboolean (*check_connection_available)(NMDevice *self, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error); + const char *specific_object, + GError **error); - gboolean (*complete_connection)(NMDevice * self, - NMConnection * connection, - const char * specific_object, + gboolean (*complete_connection)(NMDevice *self, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error); + GError **error); NMActStageReturn (*act_stage1_prepare)(NMDevice *self, NMDeviceStateReason *out_failure_reason); NMActStageReturn (*act_stage2_config)(NMDevice *self, NMDeviceStateReason *out_failure_reason); - NMActStageReturn (*act_stage3_ip_config_start)(NMDevice * self, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason); - NMActStageReturn (*act_stage4_ip_config_timeout)(NMDevice * self, - int addr_family, - NMDeviceStateReason *out_failure_reason); + void (*act_stage3_ip_config)(NMDevice *self, int addr_family); + gboolean (*ready_for_ip_config)(NMDevice *self); - void (*ip4_config_pre_commit)(NMDevice *self, NMIP4Config *config); + const char *(*get_ip_method_auto)(NMDevice *self, int addr_family); /* Async deactivating (in the DEACTIVATING phase) */ - void (*deactivate_async)(NMDevice * self, - GCancellable * cancellable, + void (*deactivate_async)(NMDevice *self, + GCancellable *cancellable, NMDeviceDeactivateCallback callback, gpointer user_data); @@ -372,13 +368,13 @@ typedef struct _NMDeviceClass { /* Update the connection with currently configured L2 settings */ void (*update_connection)(NMDevice *device, NMConnection *connection); - gboolean (*master_update_slave_connection)(NMDevice * self, - NMDevice * slave, + gboolean (*master_update_slave_connection)(NMDevice *self, + NMDevice *slave, NMConnection *connection, - GError ** error); + GError **error); - gboolean (*enslave_slave)(NMDevice * self, - NMDevice * slave, + gboolean (*enslave_slave)(NMDevice *self, + NMDevice *slave, NMConnection *connection, gboolean configure); @@ -396,12 +392,12 @@ typedef struct _NMDeviceClass { gboolean (*unmanaged_on_quit)(NMDevice *self); - gboolean (*can_reapply_change)(NMDevice * self, + gboolean (*can_reapply_change)(NMDevice *self, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error); + GError **error); void (*reapply_connection)(NMDevice *self, NMConnection *con_old, NMConnection *con_new); @@ -420,8 +416,8 @@ typedef struct _NMDeviceClass { GType nm_device_get_type(void); struct _NMDedupMultiIndex *nm_device_get_multi_index(NMDevice *self); -NMNetns * nm_device_get_netns(NMDevice *self); -NMPlatform * nm_device_get_platform(NMDevice *self); +NMNetns *nm_device_get_netns(NMDevice *self); +NMPlatform *nm_device_get_platform(NMDevice *self); const char *nm_device_get_udi(NMDevice *dev); const char *nm_device_get_iface(NMDevice *dev); @@ -437,13 +433,13 @@ _nm_device_get_iface(NMDevice *device) int nm_device_get_ifindex(NMDevice *dev); gboolean nm_device_is_software(NMDevice *dev); gboolean nm_device_is_real(NMDevice *dev); -const char * nm_device_get_ip_iface(NMDevice *dev); -const char * nm_device_get_ip_iface_from_platform(NMDevice *dev); +const char *nm_device_get_ip_iface(NMDevice *dev); +const char *nm_device_get_ip_iface_from_platform(NMDevice *dev); int nm_device_get_ip_ifindex(const NMDevice *dev); -const char * nm_device_get_driver(NMDevice *dev); -const char * nm_device_get_driver_version(NMDevice *dev); -const char * nm_device_get_type_desc(NMDevice *dev); -const char * nm_device_get_type_description(NMDevice *dev); +const char *nm_device_get_driver(NMDevice *dev); +const char *nm_device_get_driver_version(NMDevice *dev); +const char *nm_device_get_type_desc(NMDevice *dev); +const char *nm_device_get_type_description(NMDevice *dev); NMDeviceType nm_device_get_device_type(NMDevice *dev); NMLinkType nm_device_get_link_type(NMDevice *dev); NMMetered nm_device_get_metered(NMDevice *dev); @@ -460,16 +456,13 @@ const char *nm_device_get_permanent_hw_address_full(NMDevice *self, gboolean *out_is_fake); const char *nm_device_get_initial_hw_address(NMDevice *dev); -NMProxyConfig *nm_device_get_proxy_config(NMDevice *dev); - NMDhcpConfig *nm_device_get_dhcp_config(NMDevice *dev, int addr_family); -NMIP4Config * nm_device_get_ip4_config(NMDevice *dev); -void nm_device_replace_vpn4_config(NMDevice *dev, NMIP4Config *old, NMIP4Config *config); -NMIP6Config *nm_device_get_ip6_config(NMDevice *dev); -void nm_device_replace_vpn6_config(NMDevice *dev, NMIP6Config *old, NMIP6Config *config); +NML3Cfg *nm_device_get_l3cfg(NMDevice *self); + +const NML3ConfigData *nm_device_get_l3cd(NMDevice *self, gboolean get_commited); -void nm_device_capture_initial_config(NMDevice *dev); +void nm_device_l3cfg_commit(NMDevice *self, NML3CfgCommitType commit_type, gboolean commit_sync); int nm_device_parent_get_ifindex(NMDevice *dev); NMDevice *nm_device_parent_get_device(NMDevice *dev); @@ -478,7 +471,7 @@ gboolean nm_device_parent_notify_changed(NMDevice *self, NMDevice *change_candidate, gboolean device_removed); -const char *nm_device_parent_find_for_connection(NMDevice * self, +const char *nm_device_parent_find_for_connection(NMDevice *self, const char *current_setting_parent); /* Master */ @@ -487,11 +480,11 @@ gboolean nm_device_is_master(NMDevice *dev); /* Slave */ NMDevice *nm_device_get_master(NMDevice *dev); -NMActRequest * nm_device_get_act_request(NMDevice *dev); -NMSettingsConnection * nm_device_get_settings_connection(NMDevice *dev); -NMConnection * nm_device_get_settings_connection_get_connection(NMDevice *self); -NMConnection * nm_device_get_applied_connection(NMDevice *dev); -gboolean nm_device_has_unmodified_applied_connection(NMDevice * self, +NMActRequest *nm_device_get_act_request(NMDevice *dev); +NMSettingsConnection *nm_device_get_settings_connection(NMDevice *dev); +NMConnection *nm_device_get_settings_connection_get_connection(NMDevice *self); +NMConnection *nm_device_get_applied_connection(NMDevice *dev); +gboolean nm_device_has_unmodified_applied_connection(NMDevice *self, NMSettingCompareFlags compare_flags); NMActivationStateFlags nm_device_get_activation_state_flags(NMDevice *self); @@ -507,21 +500,21 @@ gboolean nm_device_has_carrier(NMDevice *dev); NMConnection *nm_device_generate_connection(NMDevice *self, NMDevice *master, gboolean *out_maybe_later, - GError ** error); + GError **error); -gboolean nm_device_master_update_slave_connection(NMDevice * master, - NMDevice * slave, +gboolean nm_device_master_update_slave_connection(NMDevice *master, + NMDevice *slave, NMConnection *connection, - GError ** error); + GError **error); gboolean nm_device_can_auto_connect(NMDevice *self, NMSettingsConnection *sett_conn, char **specific_object); -gboolean nm_device_complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +gboolean nm_device_complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error); + GError **error); gboolean nm_device_check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error); @@ -547,7 +540,7 @@ RfKillType nm_device_get_rfkill_type(NMDevice *device); /* IPv6 prefix delegation */ -void nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes); +void nm_device_request_ip6_prefixes(NMDevice *self, guint needed_prefixes); gboolean nm_device_needs_ip6_subnet(NMDevice *self); @@ -620,15 +613,15 @@ gboolean nm_device_get_managed(NMDevice *device, gboolean for_user_reque NMUnmanagedFlags nm_device_get_unmanaged_mask(NMDevice *device, NMUnmanagedFlags flag); NMUnmanagedFlags nm_device_get_unmanaged_flags(NMDevice *device, NMUnmanagedFlags flag); void nm_device_set_unmanaged_flags(NMDevice *device, NMUnmanagedFlags flags, NMUnmanFlagOp set_op); -void nm_device_set_unmanaged_by_flags(NMDevice * device, +void nm_device_set_unmanaged_by_flags(NMDevice *device, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, NMDeviceStateReason reason); -void nm_device_set_unmanaged_by_flags_queue(NMDevice * self, +void nm_device_set_unmanaged_by_flags_queue(NMDevice *self, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, NMDeviceStateReason reason); -void nm_device_set_unmanaged_by_user_settings(NMDevice *self); +void nm_device_set_unmanaged_by_user_settings(NMDevice *self, gboolean now); void nm_device_set_unmanaged_by_user_udev(NMDevice *self); void nm_device_set_unmanaged_by_user_conf(NMDevice *self); void nm_device_set_unmanaged_by_quitting(NMDevice *device); @@ -641,26 +634,26 @@ gboolean nm_device_has_capability(NMDevice *self, NMDeviceCapabilities caps); /*****************************************************************************/ -void nm_device_assume_state_get(NMDevice * self, - gboolean * out_assume_state_guess_assume, +void nm_device_assume_state_get(NMDevice *self, + gboolean *out_assume_state_guess_assume, const char **out_assume_state_connection_uuid); void nm_device_assume_state_reset(NMDevice *self); /*****************************************************************************/ -gboolean nm_device_realize_start(NMDevice * device, +gboolean nm_device_realize_start(NMDevice *device, const NMPlatformLink *plink, gboolean assume_state_guess_assume, - const char * assume_state_connection_uuid, + const char *assume_state_connection_uuid, gboolean set_nm_owned, NMUnmanFlagOp unmanaged_user_explicit, - gboolean * out_compatible, - GError ** error); + gboolean *out_compatible, + GError **error); void nm_device_realize_finish(NMDevice *self, const NMPlatformLink *plink); -gboolean nm_device_create_and_realize(NMDevice * self, +gboolean nm_device_create_and_realize(NMDevice *self, NMConnection *connection, - NMDevice * parent, - GError ** error); + NMDevice *parent, + GError **error); gboolean nm_device_unrealize(NMDevice *device, gboolean remove_resources, GError **error); void nm_device_update_from_platform_link(NMDevice *self, const NMPlatformLink *plink); @@ -686,7 +679,7 @@ typedef enum { NMDeviceAutoconnectBlockedFlags nm_device_autoconnect_blocked_get(NMDevice *device, NMDeviceAutoconnectBlockedFlags mask); -void nm_device_autoconnect_blocked_set_full(NMDevice * device, +void nm_device_autoconnect_blocked_set_full(NMDevice *device, NMDeviceAutoconnectBlockedFlags mask, NMDeviceAutoconnectBlockedFlags values); @@ -717,7 +710,7 @@ void nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateRea gboolean nm_device_get_firmware_missing(NMDevice *self); -void nm_device_disconnect_active_connection(NMActiveConnection * active, +void nm_device_disconnect_active_connection(NMActiveConnection *active, NMDeviceStateReason device_reason, NMActiveConnectionStateReason active_reason); @@ -740,11 +733,11 @@ nm_device_has_pending_action(NMDevice *device) NMSettingsConnection * nm_device_get_best_connection(NMDevice *device, const char *specific_object, GError **error); -gboolean nm_device_check_connection_available(NMDevice * device, - NMConnection * connection, +gboolean nm_device_check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error); + const char *specific_object, + GError **error); void nm_device_notify_availability_maybe_changed(NMDevice *self); @@ -754,17 +747,11 @@ NMConnection *nm_device_new_default_connection(NMDevice *self); const NMPObject *nm_device_get_best_default_route(NMDevice *self, int addr_family); -void nm_device_spawn_iface_helper(NMDevice *self); - gboolean nm_device_reapply(NMDevice *self, NMConnection *connection, GError **error); void nm_device_reapply_settings_immediately(NMDevice *self); void nm_device_update_firewall_zone(NMDevice *self); void nm_device_update_metered(NMDevice *self); -void nm_device_reactivate_ip_config(NMDevice * device, - int addr_family, - NMSettingIPConfig *s_ip_old, - NMSettingIPConfig *s_ip_new); gboolean nm_device_update_hw_address(NMDevice *self); void nm_device_update_initial_hw_address(NMDevice *self); @@ -774,24 +761,24 @@ guint nm_device_get_supplicant_timeout(NMDevice *self); gboolean nm_device_auth_retries_try_next(NMDevice *self); -gboolean nm_device_hw_addr_get_cloned(NMDevice * self, +gboolean nm_device_hw_addr_get_cloned(NMDevice *self, NMConnection *connection, gboolean is_wifi, - char ** hwaddr, - gboolean * preserve, - GError ** error); + char **hwaddr, + gboolean *preserve, + GError **error); typedef struct _NMDeviceConnectivityHandle NMDeviceConnectivityHandle; -typedef void (*NMDeviceConnectivityCallback)(NMDevice * self, +typedef void (*NMDeviceConnectivityCallback)(NMDevice *self, NMDeviceConnectivityHandle *handle, NMConnectivityState state, - GError * error, + GError *error, gpointer user_data); void nm_device_check_connectivity_update_interval(NMDevice *self); -NMDeviceConnectivityHandle *nm_device_check_connectivity(NMDevice * self, +NMDeviceConnectivityHandle *nm_device_check_connectivity(NMDevice *self, int addr_family, NMDeviceConnectivityCallback callback, gpointer user_data); @@ -806,16 +793,16 @@ typedef void (*NMBtVTableRegisterCallback)(GError *error, gpointer user_data); struct _NMBtVTableNetworkServer { gboolean (*is_available)(const NMBtVTableNetworkServer *vtable, - const char * addr, - NMDevice * device_accept_busy); + const char *addr, + NMDevice *device_accept_busy); gboolean (*register_bridge)(const NMBtVTableNetworkServer *vtable, - const char * addr, - NMDevice * device, - GCancellable * cancellable, + const char *addr, + NMDevice *device, + GCancellable *cancellable, NMBtVTableRegisterCallback callback, gpointer callback_user_data, - GError ** error); + GError **error); gboolean (*unregister_bridge)(const NMBtVTableNetworkServer *vtable, NMDevice *device); }; diff --git a/src/core/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index 4e178491..137bf8fb 100644 --- a/src/core/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -34,7 +34,7 @@ struct _NMLldpListener { sd_lldp_rx *lldp_handle; GHashTable *lldp_neighbors; - GVariant * variant; + GVariant *variant; NMLldpListenerNotify notify_callback; gpointer notify_user_data; @@ -49,10 +49,10 @@ struct _NMLldpListener { /*****************************************************************************/ typedef struct { - GVariant * variant; + GVariant *variant; sd_lldp_neighbor *neighbor_sd; - char * chassis_id; - char * port_id; + char *chassis_id; + char *port_id; guint8 chassis_id_type; guint8 port_id_type; } LldpNeighbor; @@ -112,12 +112,12 @@ lldp_neighbor_get_raw(LldpNeighbor *neigh, const guint8 **out_raw_data, gsize *o static gboolean lldp_neighbor_id_get(struct sd_lldp_neighbor *neighbor_sd, - guint8 * out_chassis_id_type, - const guint8 ** out_chassis_id, - gsize * out_chassis_id_len, - guint8 * out_port_id_type, - const guint8 ** out_port_id, - gsize * out_port_id_len) + guint8 *out_chassis_id_type, + const guint8 **out_chassis_id, + gsize *out_chassis_id_len, + guint8 *out_port_id_type, + const guint8 **out_port_id, + gsize *out_port_id_len) { int r; @@ -144,8 +144,8 @@ lldp_neighbor_id_hash(gconstpointer ptr) const LldpNeighbor *neigh = ptr; guint8 chassis_id_type; guint8 port_id_type; - const guint8 * chassis_id; - const guint8 * port_id; + const guint8 *chassis_id; + const guint8 *port_id; gsize chassis_id_len; gsize port_id_len; NMHashState h; @@ -270,9 +270,9 @@ parse_management_address_tlv(const uint8_t *data, gsize len) { GVariantBuilder builder; gsize addr_len; - const guint8 * v_object_id_arr; + const guint8 *v_object_id_arr; gsize v_object_id_len; - const guint8 * v_address_arr; + const guint8 *v_address_arr; gsize v_address_len; guint32 v_interface_number; guint32 v_interface_number_subtype; @@ -393,7 +393,7 @@ format_string(const guint8 *data, gsize len, gboolean allow_trim, char **out_to_ static char * format_string_cp(const guint8 *data, gsize len, gboolean allow_trim) { - char * s_free = NULL; + char *s_free = NULL; const char *s; s = format_string(data, len, allow_trim, &s_free); @@ -482,11 +482,11 @@ lldp_neighbor_to_variant(LldpNeighbor *neigh) { struct ether_addr destination_address; GVariantBuilder builder; - const char * str; - const guint8 * raw_data; + const char *str; + const guint8 *raw_data; gsize raw_len; uint16_t u16; - uint8_t * data8; + uint8_t *data8; gsize len; int r; @@ -537,19 +537,19 @@ lldp_neighbor_to_variant(LldpNeighbor *neigh) else { gboolean v_management_addresses_has = FALSE; GVariantBuilder v_management_addresses; - GVariant * v_ieee_802_1_pvid = NULL; - GVariant * v_ieee_802_1_ppvid = NULL; - GVariant * v_ieee_802_1_ppvid_flags = NULL; + GVariant *v_ieee_802_1_pvid = NULL; + GVariant *v_ieee_802_1_ppvid = NULL; + GVariant *v_ieee_802_1_ppvid_flags = NULL; GVariantBuilder v_ieee_802_1_ppvids; - GVariant * v_ieee_802_1_vid = NULL; - GVariant * v_ieee_802_1_vlan_name = NULL; + GVariant *v_ieee_802_1_vid = NULL; + GVariant *v_ieee_802_1_vlan_name = NULL; GVariantBuilder v_ieee_802_1_vlans; - GVariant * v_ieee_802_3_mac_phy_conf = NULL; - GVariant * v_ieee_802_3_power_via_mdi = NULL; - GVariant * v_ieee_802_3_max_frame_size = NULL; - GVariant * v_mud_url = NULL; + GVariant *v_ieee_802_3_mac_phy_conf = NULL; + GVariant *v_ieee_802_3_power_via_mdi = NULL; + GVariant *v_ieee_802_3_max_frame_size = NULL; + GVariant *v_mud_url = NULL; GVariantBuilder tmp_builder; - GVariant * tmp_variant; + GVariant *tmp_variant; do { guint8 oui[3]; @@ -636,7 +636,7 @@ lldp_neighbor_to_variant(LldpNeighbor *neigh) case SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME: { gs_free char *name_to_free = NULL; - const char * name; + const char *name; guint32 vid; gsize l; @@ -716,7 +716,7 @@ lldp_neighbor_to_variant(LldpNeighbor *neigh) case SD_LLDP_OUI_IANA_SUBTYPE_MUD: if (!v_mud_url) { gs_free char *s_free = NULL; - const char * s; + const char *s; s = format_string(data8, len, TRUE, &s_free); if (s) @@ -778,8 +778,8 @@ GVariant * nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len) { nm_auto(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *neighbor_sd = NULL; - nm_auto(lldp_neighbor_freep) LldpNeighbor * neigh = NULL; - GVariant * variant; + nm_auto(lldp_neighbor_freep) LldpNeighbor *neigh = NULL; + GVariant *variant; int r; g_assert(raw_data); @@ -846,7 +846,7 @@ static void process_lldp_neighbor(NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gboolean remove) { nm_auto(lldp_neighbor_freep) LldpNeighbor *neigh = NULL; - LldpNeighbor * neigh_old; + LldpNeighbor *neigh_old; nm_assert(self); nm_assert(self->lldp_handle); @@ -933,10 +933,10 @@ NMLldpListener * nm_lldp_listener_new(int ifindex, NMLldpListenerNotify notify_callback, gpointer notify_user_data, - GError ** error) + GError **error) { NMLldpListener *self = NULL; - sd_lldp_rx * lldp_handle; + sd_lldp_rx *lldp_handle; int r; g_return_val_if_fail(ifindex > 0, FALSE); diff --git a/src/core/devices/nm-lldp-listener.h b/src/core/devices/nm-lldp-listener.h index 762eb3d2..f2e9bcd2 100644 --- a/src/core/devices/nm-lldp-listener.h +++ b/src/core/devices/nm-lldp-listener.h @@ -13,7 +13,7 @@ typedef void (*NMLldpListenerNotify)(NMLldpListener *self, gpointer user_data); NMLldpListener *nm_lldp_listener_new(int ifindex, NMLldpListenerNotify notify_callback, gpointer notify_user_data, - GError ** error); + GError **error); void nm_lldp_listener_destroy(NMLldpListener *self); int nm_lldp_listener_get_ifindex(NMLldpListener *self); diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index 26a5ba00..683ada13 100644 --- a/src/core/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -42,11 +42,11 @@ get_type_description(NMDevice *device) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { /* The actual backing resources will be created on enslavement by the port * when it can identify the port and the bridge. */ @@ -66,13 +66,16 @@ get_generic_capabilities(NMDevice *device) return NM_DEVICE_CAP_IS_SOFTWARE; } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static gboolean +ready_for_ip_config(NMDevice *device) +{ + return FALSE; +} + +static void +act_stage3_ip_config(NMDevice *device, int addr_family) { - return NM_ACT_STAGE_RETURN_IP_FAIL; + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); } static gboolean @@ -141,7 +144,7 @@ static void nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ovs_bridge); @@ -154,7 +157,8 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) device_class->create_and_realize = create_and_realize; device_class->unrealize = unrealize; device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; device_class->enslave_slave = enslave_slave; device_class->release_slave = release_slave; device_class->can_reapply_change_ovs_external_ids = TRUE; diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 46a612ac..74707d24 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -49,11 +49,11 @@ get_type_description(NMDevice *device) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { /* The actual backing resources will be created once an interface is * added to a port of ours, since there can be neither an empty port nor @@ -71,7 +71,7 @@ get_generic_capabilities(NMDevice *device) static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); return nm_ovsdb_is_ready(priv->ovsdb); @@ -80,7 +80,7 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) static gboolean can_auto_connect(NMDevice *device, NMSettingsConnection *sett_conn, char **specific_object) { - NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); return nm_ovsdb_is_ready(priv->ovsdb); @@ -124,14 +124,19 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) { - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_CONFIG_FAILED); + nm_device_devip_set_failed(device, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + nm_device_devip_set_failed(device, AF_INET6, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; } nm_device_bring_up(device, TRUE, NULL); - nm_device_activate_schedule_stage3_ip_config_start(device); + + nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL); + nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL); + nm_device_activate_schedule_stage3_ip_config(device, FALSE); + return; } + + nm_device_activate_schedule_stage2_device_config(device, FALSE); } static gboolean @@ -149,7 +154,7 @@ _is_internal_interface(NMDevice *device) static void set_platform_mtu_cb(GError *error, gpointer user_data) { - NMDevice * device = user_data; + NMDevice *device = user_data; NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); if (error && !g_error_matches(error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) { @@ -165,7 +170,7 @@ set_platform_mtu_cb(GError *error, gpointer user_data) static gboolean set_platform_mtu(NMDevice *device, guint32 mtu) { - NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); /* @@ -188,31 +193,43 @@ set_platform_mtu(NMDevice *device, guint32 mtu) return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class)->set_platform_mtu(device, mtu); } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static gboolean +ready_for_ip_config(NMDevice *device) { - NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); - NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(device); + return nm_device_get_ip_ifindex(device) > 0; +} + +static void +act_stage3_ip_config(NMDevice *device, int addr_family) +{ + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); - if (!_is_internal_interface(device)) - return NM_ACT_STAGE_RETURN_IP_FAIL; + if (!_is_internal_interface(device)) { + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); + return; + } + /* FIXME(l3cfg): we should create the IP ifindex before stage3 start. + * + * For now it's here because when the ovs-interface enters stage3, then it's added to the + * controller (ovs-port) and the entry is create in the ovsdb. Only after that the kernel + * link appears. + * + * This should change. */ if (nm_device_get_ip_ifindex(device) <= 0) { _LOGT(LOGD_DEVICE, "waiting for link to appear"); priv->waiting_for_interface = TRUE; - return NM_ACT_STAGE_RETURN_POSTPONE; + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL); + return; } if (!nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) { - *out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; + nm_device_devip_set_failed(device, addr_family, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return; } - return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); } static gboolean @@ -224,15 +241,15 @@ can_unmanaged_external_down(NMDevice *self) static void deactivate(NMDevice *device) { - NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); priv->waiting_for_interface = FALSE; } typedef struct { - NMDeviceOvsInterface * self; - GCancellable * cancellable; + NMDeviceOvsInterface *self; + GCancellable *cancellable; NMDeviceDeactivateCallback callback; gpointer callback_user_data; gulong link_changed_id; @@ -258,14 +275,14 @@ deactivate_invoke_cb(DeactivateData *data, GError *error) } static void -deactivate_link_changed_cb(NMPlatform * platform, +deactivate_link_changed_cb(NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink *info, int change_type_i, DeactivateData *data) { - NMDeviceOvsInterface * self = data->self; + NMDeviceOvsInterface *self = data->self; const NMPlatformSignalChangeType change_type = change_type_i; if (change_type == NM_PLATFORM_SIGNAL_REMOVED @@ -280,7 +297,7 @@ deactivate_link_changed_cb(NMPlatform * platform, static gboolean deactivate_link_timeout(gpointer user_data) { - DeactivateData * data = user_data; + DeactivateData *data = user_data; NMDeviceOvsInterface *self = data->self; _LOGT(LOGD_DEVICE, "deactivate: timeout waiting link removal"); @@ -300,7 +317,7 @@ deactivate_cancelled_cb(GCancellable *cancellable, gpointer user_data) static void deactivate_cb_on_idle(gpointer user_data, GCancellable *cancellable) { - DeactivateData *data = user_data; + DeactivateData *data = user_data; gs_free_error GError *cancelled_error = NULL; g_cancellable_set_error_if_cancelled(data->cancellable, &cancelled_error); @@ -308,14 +325,14 @@ deactivate_cb_on_idle(gpointer user_data, GCancellable *cancellable) } static void -deactivate_async(NMDevice * device, - GCancellable * cancellable, +deactivate_async(NMDevice *device, + GCancellable *cancellable, NMDeviceDeactivateCallback callback, gpointer callback_user_data) { - NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); - DeactivateData * data; + DeactivateData *data; _LOGT(LOGD_CORE, "deactivate: start async"); @@ -402,7 +419,7 @@ nm_device_ovs_interface_init(NMDeviceOvsInterface *self) static void dispose(GObject *object) { - NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(object); + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(object); NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); if (priv->ovsdb) { @@ -420,9 +437,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_ovs_interface = { static void nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->dispose = dispose; @@ -443,7 +460,8 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) device_class->is_available = is_available; device_class->check_connection_compatible = check_connection_compatible; device_class->link_changed = link_changed; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; device_class->can_unmanaged_external_down = can_unmanaged_external_down; device_class->set_platform_mtu = set_platform_mtu; device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c index f11c5852..4419cfe9 100644 --- a/src/core/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -41,11 +41,11 @@ get_type_description(NMDevice *device) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { /* The port will be added to ovsdb when an interface is enslaved, * because there's no such thing like an empty port. */ @@ -59,13 +59,16 @@ get_generic_capabilities(NMDevice *device) return NM_DEVICE_CAP_IS_SOFTWARE; } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static gboolean +ready_for_ip_config(NMDevice *device) +{ + return FALSE; +} + +static void +act_stage3_ip_config(NMDevice *device, int addr_family) { - return NM_ACT_STAGE_RETURN_IP_FAIL; + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); } static void @@ -87,10 +90,10 @@ add_iface_cb(GError *error, gpointer user_data) static gboolean enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) { - NMDeviceOvsPort * self = NM_DEVICE_OVS_PORT(device); + NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device); NMActiveConnection *ac_port = NULL; NMActiveConnection *ac_bridge = NULL; - NMDevice * bridge_device; + NMDevice *bridge_device; if (!configure) return TRUE; @@ -143,18 +146,23 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) { NMDeviceOvsPort *self = NM_DEVICE_OVS_PORT(device); + _LOGI(LOGD_DEVICE, "releasing ovs interface %s", nm_device_get_ip_iface(slave)); + + /* Even if the an interface's device has gone away (e.g. externally + * removed and thus we're called with configure=FALSE), we still need + * to make sure its OVSDB entry is gone. + */ + nm_ovsdb_del_interface(nm_ovsdb_get(), + nm_device_get_iface(slave), + del_iface_cb, + g_object_ref(slave)); + if (configure) { - _LOGI(LOGD_DEVICE, "releasing ovs interface %s", nm_device_get_ip_iface(slave)); - nm_ovsdb_del_interface(nm_ovsdb_get(), - nm_device_get_iface(slave), - del_iface_cb, - g_object_ref(slave)); /* Open VSwitch is going to delete this one. We must ignore what happens * next with the interface. */ if (NM_IS_DEVICE_OVS_INTERFACE(slave)) nm_device_update_from_platform_link(slave, NULL); - } else - _LOGI(LOGD_DEVICE, "ovs interface %s was released", nm_device_get_ip_iface(slave)); + } } /*****************************************************************************/ @@ -174,7 +182,7 @@ static void nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) { NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ovs_port); @@ -186,7 +194,8 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) device_class->get_type_description = get_type_description; device_class->create_and_realize = create_and_realize; device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->ready_for_ip_config = ready_for_ip_config; device_class->enslave_slave = enslave_slave; device_class->release_slave = release_slave; device_class->can_reapply_change_ovs_external_ids = TRUE; diff --git a/src/core/devices/ovs/nm-ovs-factory.c b/src/core/devices/ovs/nm-ovs-factory.c index 6f5d8832..3ff0abf8 100644 --- a/src/core/devices/ovs/nm-ovs-factory.c +++ b/src/core/devices/ovs/nm-ovs-factory.c @@ -61,7 +61,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES( NM_SETTING_OVS_PORT_SETTING_NAME)) G_MODULE_EXPORT NMDeviceFactory * - nm_device_factory_create(GError **error) +nm_device_factory_create(GError **error) { nm_manager_set_capability(NM_MANAGER_GET, NM_CAPABILITY_OVS); return g_object_new(NM_TYPE_OVS_FACTORY, NULL); @@ -106,14 +106,14 @@ new_device_from_type(const char *name, NMDeviceType device_type) } static void -ovsdb_device_added(NMOvsdb * ovsdb, - const char * name, +ovsdb_device_added(NMOvsdb *ovsdb, + const char *name, guint device_type_i, - const char * subtype, + const char *subtype, NMDeviceFactory *self) { const NMDeviceType device_type = device_type_i; - NMDevice * device; + NMDevice *device; if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE && !NM_IN_STRSET(subtype, "internal", "patch")) { @@ -133,14 +133,14 @@ ovsdb_device_added(NMOvsdb * ovsdb, } static void -ovsdb_device_removed(NMOvsdb * ovsdb, - const char * name, +ovsdb_device_removed(NMOvsdb *ovsdb, + const char *name, guint device_type_i, - const char * subtype, + const char *subtype, NMDeviceFactory *self) { const NMDeviceType device_type = device_type_i; - NMDevice * device = NULL; + NMDevice *device = NULL; NMDeviceState device_state; gboolean is_system_interface = FALSE; @@ -149,8 +149,8 @@ ovsdb_device_removed(NMOvsdb * ovsdb, return; if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE && nm_streq0(subtype, "system")) { - NMDevice * d; - const CList * list; + NMDevice *d; + const CList *list; NMSettingOvsInterface *s_ovs_int; /* The device associated to an OVS system interface can be of @@ -165,15 +165,6 @@ ovsdb_device_removed(NMOvsdb * ovsdb, continue; if (!nm_streq0(nm_setting_ovs_interface_get_interface_type(s_ovs_int), "system")) continue; - /* Failing the system interface device is almost always the right - * thing to do when the ovsdb entry is removed. However, to avoid - * that a late device-removed signal tears down a different, - * newly-activated connection, let's also check that we have a master. - * Or in alternative, that the device is assumed/external: in such - * case it's always fine to fail the device. - */ - if (!nm_device_get_master(d) && !nm_device_sys_iface_state_is_external_or_assume(d)) - continue; device = d; } @@ -195,22 +186,23 @@ ovsdb_device_removed(NMOvsdb * ovsdb, } /* OVS system interfaces still exist even without the ovsdb entry */ - if (!is_system_interface && device_state == NM_DEVICE_STATE_UNMANAGED) { + if (!is_system_interface + && (device_state == NM_DEVICE_STATE_UNMANAGED + || device_state == NM_DEVICE_STATE_UNAVAILABLE)) nm_device_unrealize(device, TRUE, NULL); - } } static void -ovsdb_interface_failed(NMOvsdb * ovsdb, - const char * name, - const char * connection_uuid, - const char * error, +ovsdb_interface_failed(NMOvsdb *ovsdb, + const char *name, + const char *connection_uuid, + const char *error, NMDeviceFactory *self) { - NMDevice * device = NULL; - NMSettingsConnection * connection = NULL; - NMConnection * c; - const char * type; + NMDevice *device = NULL; + NMSettingsConnection *connection = NULL; + NMConnection *c; + const char *type; NMSettingOvsInterface *s_ovs_int; gboolean is_patch = FALSE; gboolean ignore; @@ -280,14 +272,14 @@ start(NMDeviceFactory *self) } static NMDevice * -create_device(NMDeviceFactory * self, - const char * iface, +create_device(NMDeviceFactory *self, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { NMDeviceType device_type = NM_DEVICE_TYPE_UNKNOWN; - const char * connection_type = NULL; + const char *connection_type = NULL; if (g_strcmp0(iface, "ovs-system") == 0) { *out_ignore = TRUE; diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index e5673347..7c45e0e4 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -30,34 +30,34 @@ #endif typedef struct { - char * port_uuid; - char * name; - char * connection_uuid; + char *port_uuid; + char *name; + char *connection_uuid; GPtrArray *interfaces; /* interface uuids */ - GArray * external_ids; + GArray *external_ids; } OpenvswitchPort; typedef struct { - char * bridge_uuid; - char * name; - char * connection_uuid; + char *bridge_uuid; + char *name; + char *connection_uuid; GPtrArray *ports; /* port uuids */ - GArray * external_ids; + GArray *external_ids; } OpenvswitchBridge; typedef struct { - char * interface_uuid; - char * name; - char * type; - char * connection_uuid; + char *interface_uuid; + char *name; + char *type; + char *connection_uuid; GArray *external_ids; } OpenvswitchInterface; /*****************************************************************************/ typedef void (*OvsdbMethodCallback)(NMOvsdb *self, - json_t * response, - GError * error, + json_t *response, + GError *error, gpointer user_data); typedef enum { @@ -77,27 +77,27 @@ typedef union { NMConnection *bridge; NMConnection *port; NMConnection *interface; - NMDevice * bridge_device; - NMDevice * interface_device; + NMDevice *bridge_device; + NMDevice *interface_device; } add_interface; struct { char *ifname; } del_interface; struct { - char * ifname; + char *ifname; guint32 mtu; } set_interface_mtu; struct { NMDeviceType device_type; - char * ifname; - char * connection_uuid; - GHashTable * exid_old; - GHashTable * exid_new; + char *ifname; + char *connection_uuid; + GHashTable *exid_old; + GHashTable *exid_new; } set_external_ids; } OvsdbMethodPayload; typedef struct { - NMOvsdb * self; + NMOvsdb *self; CList calls_lst; guint64 call_id; OvsdbCommand command; @@ -120,11 +120,11 @@ static guint signals[LAST_SIGNAL] = {0}; typedef struct { GSocketConnection *conn; - GCancellable * conn_cancellable; + GCancellable *conn_cancellable; char buf[4096]; /* Input buffer */ size_t bufp; /* Last decoded byte in the input buffer. */ - GString * input; /* JSON stream waiting for decoding. */ - GString * output; /* JSON stream to be sent. */ + GString *input; /* JSON stream waiting for decoding. */ + GString *output; /* JSON stream to be sent. */ guint64 call_id_counter; CList calls_lst_head; @@ -132,7 +132,7 @@ typedef struct { GHashTable *interfaces; /* interface uuid => OpenvswitchInterface */ GHashTable *ports; /* port uuid => OpenvswitchPort */ GHashTable *bridges; /* bridge uuid => OpenvswitchBridge */ - char * db_uuid; + char *db_uuid; guint num_failures; guint num_pending_deletions; bool ready : 1; @@ -328,25 +328,25 @@ _free_interface(OpenvswitchInterface *ovs_interface) /*****************************************************************************/ static void -_signal_emit_device_added(NMOvsdb * self, - const char * name, +_signal_emit_device_added(NMOvsdb *self, + const char *name, NMDeviceType device_type, - const char * device_subtype) + const char *device_subtype) { g_signal_emit(self, signals[DEVICE_ADDED], 0, name, (guint) device_type, device_subtype); } static void -_signal_emit_device_removed(NMOvsdb * self, - const char * name, +_signal_emit_device_removed(NMOvsdb *self, + const char *name, NMDeviceType device_type, - const char * device_subtype) + const char *device_subtype) { g_signal_emit(self, signals[DEVICE_REMOVED], 0, name, (guint) device_type, device_subtype); } static void -_signal_emit_interface_failed(NMOvsdb * self, +_signal_emit_interface_failed(NMOvsdb *self, const char *name, const char *connection_uuid, const char *error) @@ -363,14 +363,14 @@ _signal_emit_interface_failed(NMOvsdb * self, * there's no command pending completion. */ static void -ovsdb_call_method(NMOvsdb * self, +ovsdb_call_method(NMOvsdb *self, OvsdbMethodCallback callback, gpointer user_data, gboolean add_first, OvsdbCommand command, const OvsdbMethodPayload *payload) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); OvsdbMethodCall *call; /* Ensure we're not unsynchronized before we queue the method call. */ @@ -653,11 +653,11 @@ _set_port_interfaces(json_t *params, const char *ifname, json_t *new_interfaces) static json_t * _j_create_external_ids_array_new(NMConnection *connection) { - json_t * array; - const char *const * external_ids = NULL; + json_t *array; + const char *const *external_ids = NULL; guint n_external_ids = 0; guint i; - const char * uuid; + const char *uuid; NMSettingOvsExternalIDs *s_exid; nm_assert(NM_IS_CONNECTION(connection)); @@ -688,10 +688,10 @@ _j_create_external_ids_array_update(const char *connection_uuid, GHashTable *exid_new) { GHashTableIter iter; - json_t * mutations; - json_t * array; - const char * key; - const char * val; + json_t *mutations; + json_t *array; + const char *key; + const char *val; nm_assert(connection_uuid); @@ -741,21 +741,24 @@ _j_create_external_ids_array_update(const char *connection_uuid, /** * _insert_interface: * - * Returns an commands that adds new interface from a given connection. + * Returns a command that adds new interface from a given connection. */ static void -_insert_interface(json_t * params, +_insert_interface(json_t *params, NMConnection *interface, - NMDevice * interface_device, - const char * cloned_mac) + NMDevice *interface_device, + const char *cloned_mac) { - const char * type = NULL; + const char *type = NULL; NMSettingOvsInterface *s_ovs_iface; - NMSettingOvsDpdk * s_ovs_dpdk; - NMSettingOvsPatch * s_ovs_patch; - const char * dpdk_devargs; - json_t * options = json_array(); - json_t * row; + NMSettingOvsDpdk *s_ovs_dpdk; + const char *devargs; + guint32 n_rxq; + char sbuf[64]; + json_t *dpdk_array; + NMSettingOvsPatch *s_ovs_patch; + json_t *options = json_array(); + json_t *row; guint32 mtu = 0; s_ovs_iface = nm_connection_get_setting_ovs_interface(interface); @@ -778,11 +781,21 @@ _insert_interface(json_t * params, s_ovs_patch = nm_connection_get_setting_ovs_patch(interface); if (s_ovs_dpdk) { - dpdk_devargs = nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk); - if (dpdk_devargs) - json_array_append_new(options, json_pack("[[s, s]]", "dpdk-devargs", dpdk_devargs)); - else - json_array_append_new(options, json_array()); + devargs = nm_setting_ovs_dpdk_get_devargs(s_ovs_dpdk); + n_rxq = nm_setting_ovs_dpdk_get_n_rxq(s_ovs_dpdk); + + dpdk_array = json_array(); + + if (devargs) + json_array_append_new(dpdk_array, json_pack("[s,s]", "dpdk-devargs", devargs)); + + if (n_rxq != 0) { + json_array_append_new(dpdk_array, + json_pack("[s,s]", "n_rxq", nm_sprintf_buf(sbuf, "%u", n_rxq))); + } + + json_array_append_new(options, dpdk_array); + } else if (s_ovs_patch) { json_array_append_new( options, @@ -828,13 +841,13 @@ static void _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces) { NMSettingOvsPort *s_ovs_port; - const char * vlan_mode = NULL; + const char *vlan_mode = NULL; guint tag = 0; - const char * lacp = NULL; - const char * bond_mode = NULL; + const char *lacp = NULL; + const char *bond_mode = NULL; guint bond_updelay = 0; guint bond_downdelay = 0; - json_t * row; + json_t *row; s_ovs_port = nm_connection_get_setting_ovs_port(port); @@ -885,19 +898,19 @@ _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces) * Returns an commands that adds new bridge from a given connection. */ static void -_insert_bridge(json_t * params, +_insert_bridge(json_t *params, NMConnection *bridge, - NMDevice * bridge_device, - json_t * new_ports, - const char * cloned_mac) + NMDevice *bridge_device, + json_t *new_ports, + const char *cloned_mac) { NMSettingOvsBridge *s_ovs_bridge; - const char * fail_mode = NULL; + const char *fail_mode = NULL; gboolean mcast_snooping_enable = FALSE; gboolean rstp_enable = FALSE; gboolean stp_enable = FALSE; - const char * datapath_type = NULL; - json_t * row; + const char *datapath_type = NULL; + json_t *row; s_ovs_bridge = nm_connection_get_setting_ovs_bridge(bridge); @@ -977,24 +990,24 @@ _inc_next_cfg(const char *db_uuid) * a parent @port and @bridge if needed. */ static void -_add_interface(NMOvsdb * self, - json_t * params, +_add_interface(NMOvsdb *self, + json_t *params, NMConnection *bridge, NMConnection *port, NMConnection *interface, - NMDevice * bridge_device, - NMDevice * interface_device) + NMDevice *bridge_device, + NMDevice *interface_device) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); - GHashTableIter iter; - const char * port_uuid; - const char * interface_uuid; - const char * bridge_name; - const char * port_name; - const char * interface_name; - OpenvswitchBridge * ovs_bridge = NULL; - OpenvswitchPort * ovs_port = NULL; - OpenvswitchInterface *ovs_interface = NULL; + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + GHashTableIter iter; + const char *port_uuid; + const char *interface_uuid; + const char *bridge_name; + const char *port_name; + const char *interface_name; + OpenvswitchBridge *ovs_bridge = NULL; + OpenvswitchPort *ovs_port = NULL; + OpenvswitchInterface *ovs_interface = NULL; nm_auto_decref_json json_t *bridges = NULL; nm_auto_decref_json json_t *new_bridges = NULL; nm_auto_decref_json json_t *ports = NULL; @@ -1003,9 +1016,9 @@ _add_interface(NMOvsdb * self, nm_auto_decref_json json_t *new_interfaces = NULL; gboolean has_interface = FALSE; gboolean interface_is_local; - gs_free char * bridge_cloned_mac = NULL; - gs_free char * interface_cloned_mac = NULL; - GError * error = NULL; + gs_free char *bridge_cloned_mac = NULL; + gs_free char *interface_cloned_mac = NULL; + GError *error = NULL; int pi; int ii; @@ -1162,13 +1175,13 @@ _add_interface(NMOvsdb * self, static void _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); - GHashTableIter iter; - char * port_uuid; - char * interface_uuid; - OpenvswitchBridge * ovs_bridge; - OpenvswitchPort * ovs_port; - OpenvswitchInterface *ovs_interface; + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + GHashTableIter iter; + char *port_uuid; + char *interface_uuid; + OpenvswitchBridge *ovs_bridge; + OpenvswitchPort *ovs_port; + OpenvswitchInterface *ovs_interface; nm_auto_decref_json json_t *bridges = NULL; nm_auto_decref_json json_t *new_bridges = NULL; gboolean bridges_changed; @@ -1272,9 +1285,9 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) static void ovsdb_next_command(NMOvsdb *self) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); - OvsdbMethodCall * call; - char * cmd; + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + OvsdbMethodCall *call; + char *cmd; nm_auto_decref_json json_t *msg = NULL; if (!priv->conn) @@ -1420,9 +1433,9 @@ static void _uuids_to_array_inplace(GPtrArray *array, const json_t *items) { const char *key; - json_t * value; + json_t *value; size_t index = 0; - json_t * set_value; + json_t *set_value; size_t set_index; while (index < json_array_size(items)) { @@ -1475,8 +1488,8 @@ _external_ids_extract(json_t *external_ids, GArray **out_array, const char **out array = json_array_get(external_ids, 1); json_array_foreach (array, index, value) { - const char * key = json_string_value(json_array_get(value, 0)); - const char * val = json_string_value(json_array_get(value, 1)); + const char *key = json_string_value(json_array_get(value, 0)); + const char *val = json_string_value(json_array_get(value, 1)); NMUtilsNamedValue *v; if (!key || !val) @@ -1559,20 +1572,20 @@ static void ovsdb_got_update(NMOvsdb *self, json_t *msg) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - json_t * ovs = NULL; - json_t * bridge = NULL; - json_t * port = NULL; - json_t * interface = NULL; - json_t * items; - json_t * external_ids; + json_t *ovs = NULL; + json_t *bridge = NULL; + json_t *port = NULL; + json_t *interface = NULL; + json_t *items; + json_t *external_ids; json_error_t json_error = { 0, }; - void * iter; + void *iter; const char *name; const char *key; const char *type; - json_t * value; + json_t *value; if (json_unpack_ex(msg, &json_error, @@ -1602,10 +1615,10 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) } json_object_foreach (interface, key, value) { - OpenvswitchInterface *ovs_interface; + OpenvswitchInterface *ovs_interface; gs_unref_array GArray *external_ids_arr = NULL; - const char * connection_uuid = NULL; - json_t * error = NULL; + const char *connection_uuid = NULL; + json_t *error = NULL; int r; r = json_unpack(value, @@ -1726,10 +1739,10 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) json_object_foreach (port, key, value) { gs_unref_ptrarray GPtrArray *interfaces = NULL; - OpenvswitchPort * ovs_port; - gs_unref_array GArray *external_ids_arr = NULL; - const char * connection_uuid = NULL; - int r; + OpenvswitchPort *ovs_port; + gs_unref_array GArray *external_ids_arr = NULL; + const char *connection_uuid = NULL; + int r; r = json_unpack(value, "{s:{s:s, s:o, s:o}}", @@ -1827,10 +1840,10 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) json_object_foreach (bridge, key, value) { gs_unref_ptrarray GPtrArray *ports = NULL; - OpenvswitchBridge * ovs_bridge; - gs_unref_array GArray *external_ids_arr = NULL; - const char * connection_uuid = NULL; - int r; + OpenvswitchBridge *ovs_bridge; + gs_unref_array GArray *external_ids_arr = NULL; + const char *connection_uuid = NULL; + int r; r = json_unpack(value, "{s:{s:s, s:o, s:o}}", @@ -1940,9 +1953,9 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) static void ovsdb_got_echo(NMOvsdb *self, json_int_t id, json_t *data) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); - nm_auto_decref_json json_t *msg = NULL; - char * reply; + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + nm_auto_decref_json json_t *msg = NULL; + char *reply; gboolean output_was_empty; output_was_empty = priv->output->len == 0; @@ -1969,12 +1982,12 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) json_error_t json_error = { 0, }; - json_t * json_id = NULL; + json_t *json_id = NULL; json_int_t id = (json_int_t) -1; const char *method = NULL; - json_t * params = NULL; - json_t * result = NULL; - json_t * error = NULL; + json_t *params = NULL; + json_t *result = NULL; + json_t *error = NULL; if (json_unpack_ex(msg, &json_error, @@ -2020,9 +2033,9 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) } if (id >= 0) { - OvsdbMethodCall *call; + OvsdbMethodCall *call; gs_free_error GError *local = NULL; - gs_free char * msg_as_str = NULL; + gs_free char *msg_as_str = NULL; /* This is a response to a method call. */ if (c_list_is_empty(&priv->calls_lst_head)) { @@ -2078,7 +2091,7 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) static size_t _json_callback(void *buffer, size_t buflen, void *user_data) { - NMOvsdb * self = NM_OVSDB(user_data); + NMOvsdb *self = NM_OVSDB(user_data); NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); if (priv->bufp == priv->input->len) { @@ -2102,12 +2115,12 @@ _json_callback(void *buffer, size_t buflen, void *user_data) static void ovsdb_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - NMOvsdb * self = NM_OVSDB(user_data); + NMOvsdb *self = NM_OVSDB(user_data); NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - GInputStream * stream = G_INPUT_STREAM(source_object); - GError * error = NULL; + GInputStream *stream = G_INPUT_STREAM(source_object); + GError *error = NULL; gssize size; - json_t * msg; + json_t *msg; json_error_t json_error = { 0, }; @@ -2160,10 +2173,10 @@ ovsdb_read(NMOvsdb *self) static void ovsdb_write_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - GOutputStream * stream = G_OUTPUT_STREAM(source_object); - NMOvsdb * self = NM_OVSDB(user_data); + GOutputStream *stream = G_OUTPUT_STREAM(source_object); + NMOvsdb *self = NM_OVSDB(user_data); NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - GError * error = NULL; + GError *error = NULL; gssize size; size = g_output_stream_write_finish(stream, res, &error); @@ -2188,7 +2201,7 @@ static void ovsdb_write(NMOvsdb *self) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - GOutputStream * stream; + GOutputStream *stream; if (!priv->output->len) return; @@ -2221,7 +2234,7 @@ ovsdb_write(NMOvsdb *self) static void ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); OvsdbMethodCall *call; nm_assert(!retry || !is_disposing); @@ -2278,8 +2291,8 @@ _check_ready(NMOvsdb *self) static void _del_initial_iface_cb(GError *error, gpointer user_data) { - NMOvsdb * self; - gs_free char * ifname = NULL; + NMOvsdb *self; + gs_free char *ifname = NULL; NMOvsdbPrivate *priv; nm_utils_user_data_unpack(user_data, &self, &ifname); @@ -2305,9 +2318,9 @@ _del_initial_iface_cb(GError *error, gpointer user_data) static void ovsdb_cleanup_initial_interfaces(NMOvsdb *self) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); const OpenvswitchInterface *interface; - NMUtilsUserData * data; + NMUtilsUserData *data; GHashTableIter iter; if (priv->ready || priv->num_pending_deletions != 0) @@ -2352,9 +2365,9 @@ _monitor_bridges_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_ static void _ovsdb_connect_complete_with_fd(NMOvsdb *self, int fd_take) { - NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); gs_unref_object GSocket *socket = NULL; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; socket = g_socket_new_from_fd(nm_steal_fd(&fd_take), &error); if (!socket) { @@ -2374,7 +2387,7 @@ static void _ovsdb_connect_priv_helper_cb(int fd_take, GError *error, gpointer user_data) { nm_auto_close int fd = fd_take; - NMOvsdb * self; + NMOvsdb *self; if (nm_utils_error_is_cancelled(error)) return; @@ -2394,9 +2407,9 @@ _ovsdb_connect_priv_helper_cb(int fd_take, GError *error, gpointer user_data) static void _ovsdb_connect_idle(gpointer user_data, GCancellable *cancellable) { - NMOvsdb * self; - NMOvsdbPrivate * priv; - nm_auto_close int fd = -1; + NMOvsdb *self; + NMOvsdbPrivate *priv; + nm_auto_close int fd = -1; gs_free_error GError *error = NULL; if (g_cancellable_is_cancelled(cancellable)) @@ -2468,11 +2481,11 @@ typedef struct { static void _transact_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_data) { - OvsdbCall * call = user_data; + OvsdbCall *call = user_data; const char *err; const char *err_details; size_t index; - json_t * value; + json_t *value; if (error) goto out; @@ -2516,12 +2529,12 @@ nm_ovsdb_is_ready(NMOvsdb *self) } void -nm_ovsdb_add_interface(NMOvsdb * self, - NMConnection * bridge, - NMConnection * port, - NMConnection * interface, - NMDevice * bridge_device, - NMDevice * interface_device, +nm_ovsdb_add_interface(NMOvsdb *self, + NMConnection *bridge, + NMConnection *port, + NMConnection *interface, + NMDevice *bridge_device, + NMDevice *interface_device, NMOvsdbCallback callback, gpointer user_data) { @@ -2538,8 +2551,8 @@ nm_ovsdb_add_interface(NMOvsdb * self, } void -nm_ovsdb_del_interface(NMOvsdb * self, - const char * ifname, +nm_ovsdb_del_interface(NMOvsdb *self, + const char *ifname, NMOvsdbCallback callback, gpointer user_data) { @@ -2552,8 +2565,8 @@ nm_ovsdb_del_interface(NMOvsdb * self, } void -nm_ovsdb_set_interface_mtu(NMOvsdb * self, - const char * ifname, +nm_ovsdb_set_interface_mtu(NMOvsdb *self, + const char *ifname, guint32 mtu, NMOvsdbCallback callback, gpointer user_data) @@ -2567,10 +2580,10 @@ nm_ovsdb_set_interface_mtu(NMOvsdb * self, } void -nm_ovsdb_set_external_ids(NMOvsdb * self, +nm_ovsdb_set_external_ids(NMOvsdb *self, NMDeviceType device_type, - const char * ifname, - const char * connection_uuid, + const char *ifname, + const char *connection_uuid, NMSettingOvsExternalIDs *s_exid_old, NMSettingOvsExternalIDs *s_exid_new) { @@ -2618,7 +2631,7 @@ nm_ovsdb_init(NMOvsdb *self) static void dispose(GObject *object) { - NMOvsdb * self = NM_OVSDB(object); + NMOvsdb *self = NM_OVSDB(object); NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); ovsdb_disconnect(self, FALSE, TRUE); diff --git a/src/core/devices/ovs/nm-ovsdb.h b/src/core/devices/ovs/nm-ovsdb.h index d0b4d19d..a50db45a 100644 --- a/src/core/devices/ovs/nm-ovsdb.h +++ b/src/core/devices/ovs/nm-ovsdb.h @@ -27,32 +27,32 @@ NMOvsdb *nm_ovsdb_get(void); GType nm_ovsdb_get_type(void); -void nm_ovsdb_add_interface(NMOvsdb * self, - NMConnection * bridge, - NMConnection * port, - NMConnection * interface, - NMDevice * bridge_device, - NMDevice * interface_device, +void nm_ovsdb_add_interface(NMOvsdb *self, + NMConnection *bridge, + NMConnection *port, + NMConnection *interface, + NMDevice *bridge_device, + NMDevice *interface_device, NMOvsdbCallback callback, gpointer user_data); -void nm_ovsdb_del_interface(NMOvsdb * self, - const char * ifname, +void nm_ovsdb_del_interface(NMOvsdb *self, + const char *ifname, NMOvsdbCallback callback, gpointer user_data); -void nm_ovsdb_set_interface_mtu(NMOvsdb * self, - const char * ifname, +void nm_ovsdb_set_interface_mtu(NMOvsdb *self, + const char *ifname, guint32 mtu, NMOvsdbCallback callback, gpointer user_data); struct _NMSettingOvsExternalIDs; -void nm_ovsdb_set_external_ids(NMOvsdb * self, +void nm_ovsdb_set_external_ids(NMOvsdb *self, NMDeviceType device_type, - const char * ifname, - const char * connection_uuid, + const char *ifname, + const char *connection_uuid, struct _NMSettingOvsExternalIDs *s_exid_old, struct _NMSettingOvsExternalIDs *s_exid_new); diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index 3398e467..16cd2e87 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -23,7 +23,6 @@ #include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "nm-dbus-manager.h" -#include "nm-ip4-config.h" #include "libnm-std-aux/nm-dbus-compat.h" #define _NMLOG_DEVICE_TYPE NMDeviceTeam @@ -34,15 +33,15 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceTeam, PROP_CONFIG, ); typedef struct { - struct teamdctl * tdc; - char * config; + struct teamdctl *tdc; + char *config; GPid teamd_pid; guint teamd_process_watch; guint teamd_timeout; guint teamd_read_timeout; guint teamd_dbus_watch; bool kill_in_progress : 1; - GFileMonitor * usock_monitor; + GFileMonitor *usock_monitor; NMDeviceStageState stage1_state : 3; } NMDeviceTeamPrivate; @@ -73,11 +72,11 @@ get_generic_capabilities(NMDevice *device) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { nm_utils_complete_generic(nm_device_get_platform(device), connection, @@ -97,7 +96,7 @@ complete_connection(NMDevice * device, static gboolean ensure_teamd_connection(NMDevice *device) { - NMDeviceTeam * self = NM_DEVICE_TEAM(device); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); int err; @@ -126,7 +125,7 @@ static gboolean teamd_read_config(NMDeviceTeam *self) { NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - const char * config = NULL; + const char *config = NULL; int err; if (priv->tdc) { @@ -151,7 +150,7 @@ teamd_read_config(NMDeviceTeam *self) static gboolean teamd_read_timeout_cb(gpointer user_data) { - NMDeviceTeam * self = user_data; + NMDeviceTeam *self = user_data; NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); priv->teamd_read_timeout = 0; @@ -162,10 +161,10 @@ teamd_read_timeout_cb(gpointer user_data) static void update_connection(NMDevice *device, NMConnection *connection) { - NMDeviceTeam * self = NM_DEVICE_TEAM(device); - NMSettingTeam * s_team = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TEAM); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); + NMSettingTeam *s_team = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TEAM); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - struct teamdctl * tdc = priv->tdc; + struct teamdctl *tdc = priv->tdc; /* Read the configuration only if not already set */ if (!priv->config && ensure_teamd_connection(device)) @@ -184,18 +183,18 @@ update_connection(NMDevice *device, NMConnection *connection) /*****************************************************************************/ static gboolean -master_update_slave_connection(NMDevice * self, - NMDevice * slave, +master_update_slave_connection(NMDevice *self, + NMDevice *slave, NMConnection *connection, - GError ** error) + GError **error) { NMSettingTeamPort *s_port; - char * port_config = NULL; + char *port_config = NULL; int err = 0; - struct teamdctl * tdc; - const char * team_port_config = NULL; - const char * iface = nm_device_get_iface(self); - const char * iface_slave = nm_device_get_iface(slave); + struct teamdctl *tdc; + const char *team_port_config = NULL; + const char *iface = nm_device_get_iface(self); + const char *iface_slave = nm_device_get_iface(slave); tdc = teamdctl_alloc(); if (!tdc) { @@ -260,7 +259,7 @@ static void teamd_kill_cb(pid_t pid, gboolean success, int child_status, void *user_data) { gs_unref_object NMDeviceTeam *self = user_data; - NMDeviceTeamPrivate * priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); priv->kill_in_progress = FALSE; @@ -308,8 +307,8 @@ teamd_cleanup(NMDeviceTeam *self, gboolean free_tdc) static gboolean teamd_timeout_cb(gpointer user_data) { - NMDeviceTeam * self = NM_DEVICE_TEAM(user_data); - NMDevice * device = NM_DEVICE(self); + NMDeviceTeam *self = NM_DEVICE_TEAM(user_data); + NMDevice *device = NM_DEVICE(self); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); g_return_val_if_fail(priv->teamd_timeout, FALSE); @@ -343,7 +342,7 @@ static void teamd_ready(NMDeviceTeam *self) { NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); gboolean success; if (priv->kill_in_progress) { @@ -382,7 +381,7 @@ teamd_ready(NMDeviceTeam *self) static void teamd_gone(NMDeviceTeam *self) { - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceState state; teamd_cleanup(self, TRUE); @@ -400,11 +399,11 @@ teamd_gone(NMDeviceTeam *self) static void teamd_dbus_appeared(GDBusConnection *connection, - const char * name, - const char * name_owner, + const char *name, + const char *name_owner, gpointer user_data) { - NMDeviceTeam * self = NM_DEVICE_TEAM(user_data); + NMDeviceTeam *self = NM_DEVICE_TEAM(user_data); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); g_return_if_fail(priv->teamd_dbus_watch); @@ -452,7 +451,7 @@ teamd_dbus_appeared(GDBusConnection *connection, static void teamd_dbus_vanished(GDBusConnection *dbus_connection, const char *name, gpointer user_data) { - NMDeviceTeam * self = NM_DEVICE_TEAM(user_data); + NMDeviceTeam *self = NM_DEVICE_TEAM(user_data); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); g_return_if_fail(priv->teamd_dbus_watch); @@ -472,9 +471,9 @@ teamd_dbus_vanished(GDBusConnection *dbus_connection, const char *name, gpointer } static void -monitor_changed_cb(GFileMonitor * monitor, - GFile * file, - GFile * other_file, +monitor_changed_cb(GFileMonitor *monitor, + GFile *file, + GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { @@ -496,9 +495,9 @@ monitor_changed_cb(GFileMonitor * monitor, static void teamd_process_watch_cb(GPid pid, int status, gpointer user_data) { - NMDeviceTeam * self = NM_DEVICE_TEAM(user_data); + NMDeviceTeam *self = NM_DEVICE_TEAM(user_data); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceState state = nm_device_get_state(device); g_return_if_fail(priv->teamd_process_watch); @@ -546,8 +545,8 @@ static gboolean teamd_kill(NMDeviceTeam *self, const char *teamd_binary, GError **error) { gs_unref_ptrarray GPtrArray *argv = NULL; - gs_free char * tmp_str = NULL; - gs_free const char ** envp = NULL; + gs_free char *tmp_str = NULL; + gs_free const char **envp = NULL; if (!teamd_binary) { teamd_binary = nm_utils_find_helper("teamd", NULL, error); @@ -582,18 +581,18 @@ teamd_kill(NMDeviceTeam *self, const char *teamd_binary, GError **error) static gboolean teamd_start(NMDeviceTeam *self) { - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - const char * iface = nm_device_get_ip_iface(NM_DEVICE(self)); - NMConnection * connection; - gs_unref_ptrarray GPtrArray *argv = NULL; - gs_free_error GError * error = NULL; - gs_free char * tmp_str = NULL; - const char * teamd_binary; - const char * config; - nm_auto_free const char *config_free = NULL; - NMSettingTeam * s_team; - gs_free char * cloned_mac = NULL; - gs_free const char ** envp = NULL; + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + const char *iface = nm_device_get_ip_iface(NM_DEVICE(self)); + NMConnection *connection; + gs_unref_ptrarray GPtrArray *argv = NULL; + gs_free_error GError *error = NULL; + gs_free char *tmp_str = NULL; + const char *teamd_binary; + const char *config; + nm_auto_free const char *config_free = NULL; + NMSettingTeam *s_team; + gs_free char *cloned_mac = NULL; + gs_free const char **envp = NULL; connection = nm_device_get_applied_connection(NM_DEVICE(self)); @@ -640,7 +639,7 @@ teamd_start(NMDeviceTeam *self) } if (cloned_mac) { - json_t * json, *hwaddr; + json_t *json, *hwaddr; json_error_t jerror; /* Inject the hwaddr property into the JSON configuration. @@ -707,11 +706,11 @@ teamd_start(NMDeviceTeam *self) static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceTeam * self = NM_DEVICE_TEAM(device); - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); gs_free_error GError *error = NULL; - NMSettingTeam * s_team; - const char * cfg; + NMSettingTeam *s_team; + const char *cfg; if (nm_device_sys_iface_state_is_external(device)) return NM_ACT_STAGE_RETURN_SUCCESS; @@ -774,7 +773,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static void deactivate(NMDevice *device) { - NMDeviceTeam * self = NM_DEVICE_TEAM(device); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; @@ -794,11 +793,11 @@ deactivate(NMDevice *device) static gboolean enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gboolean configure) { - NMDeviceTeam * self = NM_DEVICE_TEAM(device); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); gboolean success = TRUE; - const char * slave_iface = nm_device_get_ip_iface(slave); - NMSettingTeamPort * s_team_port; + const char *slave_iface = nm_device_get_ip_iface(slave); + NMSettingTeamPort *s_team_port; nm_device_master_check_slave_physical_port(device, slave, LOGD_TEAM); @@ -852,10 +851,10 @@ enslave_slave(NMDevice *device, NMDevice *slave, NMConnection *connection, gbool static void release_slave(NMDevice *device, NMDevice *slave, gboolean configure) { - NMDeviceTeam * self = NM_DEVICE_TEAM(device); + NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); gboolean do_release, success; - NMSettingTeamPort * s_port; + NMSettingTeamPort *s_port; int ifindex_slave; int ifindex; @@ -902,11 +901,11 @@ release_slave(NMDevice *device, NMDevice *slave, gboolean configure) } static gboolean -create_and_realize(NMDevice * device, - NMConnection * connection, - NMDevice * parent, +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, const NMPlatformLink **out_plink, - GError ** error) + GError **error) { const char *iface = nm_device_get_iface(device); int r; @@ -954,11 +953,11 @@ nm_device_team_init(NMDeviceTeam *self) static void constructed(GObject *object) { - NMDevice * device = NM_DEVICE(object); - NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(device); - gs_free char * tmp_str = NULL; - gs_unref_object GFile *file = NULL; - GError * error; + NMDevice *device = NM_DEVICE(object); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(device); + gs_free char *tmp_str = NULL; + gs_unref_object GFile *file = NULL; + GError *error; G_OBJECT_CLASS(nm_device_team_parent_class)->constructed(object); @@ -1006,7 +1005,7 @@ nm_device_team_new(const char *iface) static void dispose(GObject *object) { - NMDeviceTeam * self = NM_DEVICE_TEAM(object); + NMDeviceTeam *self = NM_DEVICE_TEAM(object); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); if (priv->teamd_dbus_watch) { @@ -1040,9 +1039,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_team = { static void nm_device_team_class_init(NMDeviceTeamClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructed = constructed; object_class->dispose = dispose; diff --git a/src/core/devices/team/nm-team-factory.c b/src/core/devices/team/nm-team-factory.c index e2040d19..b446cbd0 100644 --- a/src/core/devices/team/nm-team-factory.c +++ b/src/core/devices/team/nm-team-factory.c @@ -43,7 +43,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES(NM_DEVICE_FACTORY_DECLARE_LINK_TYPES( NM_LINK_TYPE_TEAM) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_TEAM_SETTING_NAME)) G_MODULE_EXPORT NMDeviceFactory * - nm_device_factory_create(GError **error) +nm_device_factory_create(GError **error) { nm_manager_set_capability(NM_MANAGER_GET, NM_CAPABILITY_TEAM); return g_object_new(NM_TYPE_TEAM_FACTORY, NULL); @@ -52,11 +52,11 @@ G_MODULE_EXPORT NMDeviceFactory * /*****************************************************************************/ static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { return nm_device_team_new(iface); } diff --git a/src/core/devices/tests/meson.build b/src/core/devices/tests/meson.build index 1bc88370..871c3206 100644 --- a/src/core/devices/tests/meson.build +++ b/src/core/devices/tests/meson.build @@ -1,7 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later test_units = [ - 'test-acd', 'test-lldp', ] diff --git a/src/core/devices/tests/test-acd.c b/src/core/devices/tests/test-acd.c deleted file mode 100644 index b4b65165..00000000 --- a/src/core/devices/tests/test-acd.c +++ /dev/null @@ -1,259 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "n-acd/src/n-acd.h" - -#include <linux/if_ether.h> - -#include "devices/nm-acd-manager.h" -#include "platform/tests/test-common.h" - -#define IFACE_VETH0 "nm-test-veth0" -#define IFACE_VETH1 "nm-test-veth1" - -#define ADDR1 0x01010101 -#define ADDR2 0x02020202 -#define ADDR3 0x03030303 -#define ADDR4 0x04040404 - -/*****************************************************************************/ - -static gboolean -_skip_acd_test_check(void) -{ - NAcd * acd; - NAcdConfig * config; - const guint8 hwaddr[ETH_ALEN] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; - int r; - static int skip = -1; - - if (skip == -1) { - r = n_acd_config_new(&config); - g_assert(r == 0); - - n_acd_config_set_ifindex(config, 1); - n_acd_config_set_transport(config, N_ACD_TRANSPORT_ETHERNET); - n_acd_config_set_mac(config, hwaddr, sizeof(hwaddr)); - - r = n_acd_new(&acd, config); - n_acd_config_free(config); - if (r == 0) - n_acd_unref(acd); - - skip = (r != 0); - } - return skip; -} - -#define _skip_acd_test() \ - ({ \ - gboolean _skip = _skip_acd_test_check(); \ - \ - if (_skip) \ - g_test_skip("Cannot create NAcd. Running under valgind?"); \ - _skip; \ - }) - -/*****************************************************************************/ - -typedef struct { - int ifindex0; - int ifindex1; - const guint8 *hwaddr0; - const guint8 *hwaddr1; - size_t hwaddr0_len; - size_t hwaddr1_len; -} test_fixture; - -static void -fixture_setup(test_fixture *fixture, gconstpointer user_data) -{ - /* create veth pair. */ - fixture->ifindex0 = - nmtstp_link_veth_add(NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex; - fixture->ifindex1 = - nmtstp_link_get_typed(NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex; - - g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex0, IFF_UP, TRUE) >= 0); - g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex1, IFF_UP, TRUE) >= 0); - - fixture->hwaddr0 = - nm_platform_link_get_address(NM_PLATFORM_GET, fixture->ifindex0, &fixture->hwaddr0_len); - fixture->hwaddr1 = - nm_platform_link_get_address(NM_PLATFORM_GET, fixture->ifindex1, &fixture->hwaddr1_len); -} - -typedef struct { - in_addr_t addresses[8]; - in_addr_t peer_addresses[8]; - gboolean expected_result[8]; -} TestInfo; - -static void -acd_manager_probe_terminated(NMAcdManager *acd_manager, gpointer user_data) -{ - g_main_loop_quit(user_data); -} - -static void -test_acd_common(test_fixture *fixture, TestInfo *info) -{ - nm_auto_free_acdmgr NMAcdManager *manager = NULL; - nm_auto_unref_gmainloop GMainLoop *loop = NULL; - int i; - const guint WAIT_TIME_OPTIMISTIC = 50; - guint wait_time; - static const NMAcdCallbacks callbacks = { - .probe_terminated_callback = acd_manager_probe_terminated, - .user_data_destroy = (GDestroyNotify) g_main_loop_unref, - }; - int r; - - if (_skip_acd_test()) - return; - - /* first, try with a short waittime. We hope that this is long enough - * to successfully complete the test. Only if that's not the case, we - * assume the computer is currently busy (high load) and we retry with - * a longer timeout. */ - wait_time = WAIT_TIME_OPTIMISTIC; -again: - - nm_clear_pointer(&loop, g_main_loop_unref); - loop = g_main_loop_new(NULL, FALSE); - - nm_clear_pointer(&manager, nm_acd_manager_free); - manager = nm_acd_manager_new(fixture->ifindex0, - fixture->hwaddr0, - fixture->hwaddr0_len, - &callbacks, - g_main_loop_ref(loop)); - g_assert(manager != NULL); - - for (i = 0; info->addresses[i]; i++) - g_assert(nm_acd_manager_add_address(manager, info->addresses[i])); - - for (i = 0; info->peer_addresses[i]; i++) { - nmtstp_ip4_address_add(NULL, - FALSE, - fixture->ifindex1, - info->peer_addresses[i], - 24, - 0, - 3600, - 1800, - 0, - NULL); - } - - r = nm_acd_manager_start_probe(manager, wait_time); - g_assert_cmpint(r, ==, 0); - - g_assert(nmtst_main_loop_run(loop, 2000)); - - for (i = 0; info->addresses[i]; i++) { - gboolean val; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - val = nm_acd_manager_check_address(manager, info->addresses[i]); - if (val == info->expected_result[i]) - continue; - - if (wait_time == WAIT_TIME_OPTIMISTIC) { - /* probably we just had a glitch and the system took longer than - * expected. Re-verify with a large timeout this time. */ - wait_time = 1000; - goto again; - } - - g_error("expected check for address #%d (%s) to %s, but it didn't", - i, - _nm_utils_inet4_ntop(info->addresses[i], sbuf), - info->expected_result[i] ? "detect no duplicated" : "detect a duplicate"); - } -} - -static void -test_acd_probe_1(test_fixture *fixture, gconstpointer user_data) -{ - TestInfo info = {.addresses = {ADDR1, ADDR2, ADDR3}, - .peer_addresses = {ADDR4}, - .expected_result = {TRUE, TRUE, TRUE}}; - - test_acd_common(fixture, &info); -} - -static void -test_acd_probe_2(test_fixture *fixture, gconstpointer user_data) -{ - TestInfo info = {.addresses = {ADDR1, ADDR2, ADDR3, ADDR4}, - .peer_addresses = {ADDR3, ADDR2}, - .expected_result = {TRUE, FALSE, FALSE, TRUE}}; - - test_acd_common(fixture, &info); -} - -static void -test_acd_announce(test_fixture *fixture, gconstpointer user_data) -{ - nm_auto_free_acdmgr NMAcdManager *manager = NULL; - nm_auto_unref_gmainloop GMainLoop *loop = NULL; - int r; - - if (_skip_acd_test()) - return; - - manager = - nm_acd_manager_new(fixture->ifindex0, fixture->hwaddr0, fixture->hwaddr0_len, NULL, NULL); - g_assert(manager != NULL); - - g_assert(nm_acd_manager_add_address(manager, ADDR1)); - g_assert(nm_acd_manager_add_address(manager, ADDR2)); - - loop = g_main_loop_new(NULL, FALSE); - r = nm_acd_manager_announce_addresses(manager); - g_assert_cmpint(r, ==, 0); - g_assert(!nmtst_main_loop_run(loop, 200)); -} - -static void -fixture_teardown(test_fixture *fixture, gconstpointer user_data) -{ - nm_platform_link_delete(NM_PLATFORM_GET, fixture->ifindex0); - nm_platform_link_delete(NM_PLATFORM_GET, fixture->ifindex1); -} - -NMTstpSetupFunc const _nmtstp_setup_platform_func = nm_linux_platform_setup; - -void -_nmtstp_init_tests(int *argc, char ***argv) -{ - nmtst_init_with_logging(argc, argv, NULL, "ALL"); -} - -void -_nmtstp_setup_tests(void) -{ - g_test_add("/acd/probe/1", - test_fixture, - NULL, - fixture_setup, - test_acd_probe_1, - fixture_teardown); - g_test_add("/acd/probe/2", - test_fixture, - NULL, - fixture_setup, - test_acd_probe_2, - fixture_teardown); - g_test_add("/acd/announce", - test_fixture, - NULL, - fixture_setup, - test_acd_announce, - fixture_teardown); -} diff --git a/src/core/devices/tests/test-lldp.c b/src/core/devices/tests/test-lldp.c index c64c7c11..048410c1 100644 --- a/src/core/devices/tests/test-lldp.c +++ b/src/core/devices/tests/test-lldp.c @@ -22,15 +22,15 @@ /*****************************************************************************/ static GVariant * -get_lldp_neighbor(GVariant * neighbors, +get_lldp_neighbor(GVariant *neighbors, int chassis_id_type, const char *chassis_id, int port_id_type, const char *port_id) { GVariantIter iter; - GVariant * variant; - GVariant * result = NULL; + GVariant *variant; + GVariant *result = NULL; nmtst_assert_variant_is_of_type(neighbors, G_VARIANT_TYPE("aa{sv}")); @@ -81,15 +81,15 @@ typedef struct { typedef struct { gsize frame_len; const uint8_t *frame; - const char * as_variant; + const char *as_variant; } TestRecvFrame; #define TEST_RECV_FRAME_DEFINE(name, _as_variant, ...) \ static const guint8 _##name##_v[] = {__VA_ARGS__}; \ static const TestRecvFrame name = { \ - .as_variant = _as_variant, \ - .frame_len = sizeof(_##name##_v), \ - .frame = _##name##_v, \ + .as_variant = _as_variant, \ + .frame_len = sizeof(_##name##_v), \ + .frame = _##name##_v, \ } typedef struct { @@ -183,7 +183,7 @@ TEST_RECV_FRAME_DEFINE( static void _test_recv_data0_check_do(GMainLoop *loop, NMLldpListener *listener, const TestRecvFrame *frame) { - GVariant * neighbors, *attr; + GVariant *neighbors, *attr; gs_unref_variant GVariant *neighbor = NULL; neighbors = nm_lldp_listener_get_neighbors(listener); @@ -537,10 +537,10 @@ TEST_RECV_FRAME_DEFINE( static void _test_recv_data1_check(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info) { - GVariant * neighbors, *attr, *child; + GVariant *neighbors, *attr, *child; gs_unref_variant GVariant *neighbor = NULL; guint v_uint = 0; - const char * v_str = NULL; + const char *v_str = NULL; neighbors = nm_lldp_listener_get_neighbors(listener); nmtst_assert_variant_is_of_type(neighbors, G_VARIANT_TYPE("aa{sv}")); @@ -868,12 +868,12 @@ lldp_neighbors_changed(NMLldpListener *lldp_listener, gpointer user_data) static void test_recv(TestRecvFixture *fixture, gconstpointer user_data) { - const TestRecvData * data = user_data; - NMLldpListener * listener; - GMainLoop * loop; + const TestRecvData *data = user_data; + NMLldpListener *listener; + GMainLoop *loop; TestRecvCallbackInfo info = {}; gsize i_frames; - GError * error = NULL; + GError *error = NULL; guint sd_id; if (fixture->ifindex == 0) { @@ -918,10 +918,10 @@ _test_recv_fixture_teardown(TestRecvFixture *fixture, gconstpointer user_data) static void test_parse_frames(gconstpointer test_data) { - const TestRecvFrame *frame = test_data; + const TestRecvFrame *frame = test_data; gs_unref_variant GVariant *v_neighbor = NULL; gs_unref_variant GVariant *attr = NULL; - gs_free char * as_variant = NULL; + gs_free char *as_variant = NULL; v_neighbor = nmtst_lldp_parse_from_raw(frame->frame, frame->frame_len); g_assert(v_neighbor); diff --git a/src/core/devices/wifi/meson.build b/src/core/devices/wifi/meson.build index 85553c53..715bc0c9 100644 --- a/src/core/devices/wifi/meson.build +++ b/src/core/devices/wifi/meson.build @@ -4,6 +4,7 @@ iwd_sources = files() if enable_iwd iwd_sources += files( 'nm-device-iwd.c', + 'nm-device-iwd-p2p.c', 'nm-iwd-manager.c', ) endif diff --git a/src/core/devices/wifi/nm-device-iwd-p2p.c b/src/core/devices/wifi/nm-device-iwd-p2p.c new file mode 100644 index 00000000..01774b12 --- /dev/null +++ b/src/core/devices/wifi/nm-device-iwd-p2p.c @@ -0,0 +1,1262 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021 Intel Corporation + */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-device-iwd-p2p.h" + +#include "NetworkManagerUtils.h" +#include "devices/nm-device-private.h" +#include "nm-act-request.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-std-aux/nm-dbus-compat.h" +#include "nm-setting-wifi-p2p.h" +#include "nm-utils.h" +#include "nm-wifi-p2p-peer.h" +#include "nm-iwd-manager.h" +#include "settings/nm-settings.h" + +#define _NMLOG_DEVICE_TYPE NMDeviceIwdP2P +#include "devices/nm-device-logging.h" + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceIwdP2P, PROP_PEERS, ); + +typedef struct { + GDBusObject *dbus_obj; + GDBusProxy *dbus_p2p_proxy; + GDBusProxy *dbus_peer_proxy; + CList peers_lst_head; + + GSource *find_peer_timeout_source; + GSource *peer_dump_source; + + GCancellable *find_cancellable; + GCancellable *connect_cancellable; + + bool enabled : 1; + + bool stage2_ready : 1; + + bool wfd_registered : 1; +} NMDeviceIwdP2PPrivate; + +struct _NMDeviceIwdP2P { + NMDevice parent; + NMDeviceIwdP2PPrivate _priv; +}; + +struct _NMDeviceIwdP2PClass { + NMDeviceClass parent; +}; + +G_DEFINE_TYPE(NMDeviceIwdP2P, nm_device_iwd_p2p, NM_TYPE_DEVICE) + +#define NM_DEVICE_IWD_P2P_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDeviceIwdP2P, NM_IS_DEVICE_IWD_P2P, NMDevice) + +/*****************************************************************************/ + +static const NMDBusInterfaceInfoExtended interface_info_device_wifi_p2p; +static const GDBusSignalInfo nm_signal_info_wifi_p2p_peer_added; +static const GDBusSignalInfo nm_signal_info_wifi_p2p_peer_removed; +static gboolean iwd_discovery_timeout_cb(gpointer user_data); + +/*****************************************************************************/ + +static void +_peer_dump(NMDeviceIwdP2P *self, + NMLogLevel log_level, + const NMWifiP2PPeer *peer, + const char *prefix, + gint32 now_s) +{ + char buf[1024]; + + _NMLOG(log_level, + LOGD_WIFI_SCAN, + "wifi-peer: %-7s %s", + prefix, + nm_wifi_p2p_peer_to_string(peer, buf, sizeof(buf), now_s)); +} + +static gboolean +peer_list_dump(gpointer user_data) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(user_data); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + nm_clear_g_source_inst(&priv->peer_dump_source); + + if (_LOGD_ENABLED(LOGD_WIFI_SCAN)) { + NMWifiP2PPeer *peer; + gint32 now_s = nm_utils_get_monotonic_timestamp_sec(); + + _LOGD(LOGD_WIFI_SCAN, "P2P Peers: [now:%u]", now_s); + c_list_for_each_entry (peer, &priv->peers_lst_head, peers_lst) + _peer_dump(self, LOGL_DEBUG, peer, "dump", now_s); + } + + return G_SOURCE_REMOVE; +} + +static void +schedule_peer_list_dump(NMDeviceIwdP2P *self) +{ + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + if (!priv->peer_dump_source && _LOGD_ENABLED(LOGD_WIFI_SCAN)) { + priv->peer_dump_source = nm_g_timeout_add_seconds_source(1, peer_list_dump, self); + } +} + +/*****************************************************************************/ + +static gboolean +is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + return priv->enabled; +} + +static gboolean +check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingWifiP2P *s_wifi_p2p; + GBytes *wfd_ies; + NMSettingIPConfig *s_ip; + + if (!NM_DEVICE_CLASS(nm_device_iwd_p2p_parent_class) + ->check_connection_compatible(device, connection, error)) + return FALSE; + + s_wifi_p2p = + NM_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P)); + + /* Any of the existing values other than DISABLED is ok */ + if (nm_setting_wifi_p2p_get_wps_method(s_wifi_p2p) + == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "No WPS method enabled"); + return FALSE; + } + + wfd_ies = nm_setting_wifi_p2p_get_wfd_ies(s_wifi_p2p); + if (wfd_ies && !nm_wifi_utils_parse_wfd_ies(wfd_ies, NULL)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "Can't parse connection WFD IEs"); + return FALSE; + } + + s_ip = NM_SETTING_IP_CONFIG(nm_connection_get_setting_ip4_config(connection)); + if (s_ip + && !NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip), + NULL, + NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "P2P implies 'auto' IPv4 config method"); + return FALSE; + } + + return TRUE; +} + +static gboolean +check_connection_available(NMDevice *device, + NMConnection *connection, + NMDeviceCheckConAvailableFlags flags, + const char *specific_object, + GError **error) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + NMSettingWifiP2P *s_wifi_p2p; + GBytes *wfd_ies; + NMWifiP2PPeer *peer; + + if (specific_object) { + peer = nm_wifi_p2p_peer_lookup_for_device(NM_DEVICE(self), specific_object); + if (!peer) { + g_set_error(error, + NM_UTILS_ERROR, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "The P2P peer %s is unknown", + specific_object); + return FALSE; + } + + if (!nm_wifi_p2p_peer_check_compatible(peer, connection, FALSE)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "Requested P2P peer is not compatible with profile"); + return FALSE; + } + } else { + peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection, FALSE); + if (!peer) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "No compatible P2P peer found"); + return FALSE; + } + } + + s_wifi_p2p = + NM_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P)); + wfd_ies = nm_setting_wifi_p2p_get_wfd_ies(s_wifi_p2p); + if (wfd_ies) { + NMIwdWfdInfo wfd_info = {}; + + if (!nm_wifi_utils_parse_wfd_ies(wfd_ies, &wfd_info)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "Can't parse connection WFD IEs"); + return FALSE; + } + + if (!nm_iwd_manager_check_wfd_info_compatible(nm_iwd_manager_get(), &wfd_info)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "An incompatible WFD connection is active"); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, + NMConnection *const *existing_connections, + GError **error) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + gs_free char *setting_name = NULL; + NMSettingWifiP2P *s_wifi_p2p; + NMWifiP2PPeer *peer; + const char *setting_peer; + + s_wifi_p2p = + NM_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P)); + + if (!specific_object) { + /* If not given a specific object, we need at minimum a peer address */ + if (!s_wifi_p2p) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A '%s' setting is required if no Peer path was given", + NM_SETTING_WIFI_P2P_SETTING_NAME); + return FALSE; + } + + setting_peer = nm_setting_wifi_p2p_get_peer(s_wifi_p2p); + if (!setting_peer) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A '%s' setting with a valid Peer is required if no Peer path was given", + NM_SETTING_WIFI_P2P_SETTING_NAME); + return FALSE; + } + } else { + peer = nm_wifi_p2p_peer_lookup_for_device(NM_DEVICE(self), specific_object); + if (!peer) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, + "The P2P peer %s is unknown", + specific_object); + return FALSE; + } + + setting_peer = nm_wifi_p2p_peer_get_address(peer); + g_return_val_if_fail(setting_peer, FALSE); + } + + /* Add a Wi-Fi P2P setting if one doesn't exist yet */ + s_wifi_p2p = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIFI_P2P); + + g_object_set(G_OBJECT(s_wifi_p2p), NM_SETTING_WIFI_P2P_PEER, setting_peer, NULL); + + setting_name = g_strdup_printf("Wi-Fi P2P Peer %s", setting_peer); + nm_utils_complete_generic(nm_device_get_platform(device), + connection, + NM_SETTING_WIFI_P2P_SETTING_NAME, + existing_connections, + setting_name, + setting_name, + NULL, + NULL, + TRUE); + + return TRUE; +} + +static gboolean +get_enabled(NMDevice *device) +{ + return NM_DEVICE_IWD_P2P_GET_PRIVATE(device)->enabled; +} + +static void +set_enabled_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMDeviceIwdP2P *self = user_data; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + + variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); + if (!variant) { + _LOGE(LOGD_DEVICE | LOGD_WIFI, ".Set failed: %s", error->message); + return; + } + _LOGD(LOGD_DEVICE | LOGD_WIFI, ".Set OK!"); +} + +static void +set_enabled(NMDevice *device, gboolean enabled) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + enabled = !!enabled; + + if (priv->enabled == enabled) + return; + + _LOGD(LOGD_WIFI, "device will be %s", enabled ? "enabled" : "disabled"); + + g_dbus_proxy_call( + priv->dbus_p2p_proxy, + DBUS_INTERFACE_PROPERTIES ".Set", + g_variant_new("(ssv)", NM_IWD_P2P_INTERFACE, "Enabled", g_variant_new("b", enabled)), + G_DBUS_CALL_FLAGS_NONE, + 2000, + NULL, + set_enabled_cb, + self); +} + +static void +p2p_properties_changed_cb(GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidate_properties, + gpointer user_data) +{ + NMDeviceIwdP2P *self = user_data; + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); + gboolean new_bool; + + if (g_variant_lookup(changed_properties, "Enabled", "b", &new_bool) + && new_bool != priv->enabled) { + priv->enabled = new_bool; + + _LOGD(LOGD_WIFI, "device now %s", priv->enabled ? "enabled" : "disabled"); + + if (priv->enabled) { + NMDeviceState state = nm_device_get_state(device); + + if (state != NM_DEVICE_STATE_UNAVAILABLE) + _LOGW(LOGD_CORE, "not in expected unavailable state!"); + + nm_device_queue_recheck_available(device, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } else { + nm_device_state_changed(device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + } + } +} + +static void +iwd_request_discovery_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMDeviceIwdP2P *self = user_data; + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + + variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); + if (!variant) { + NMDevice *device = NM_DEVICE(self); + + _LOGE(LOGD_DEVICE | LOGD_WIFI, + "%s(wifi-p2p) IWD p2p.Device.RequestDiscovery failed: %s", + nm_device_is_activating(device) ? "Activation: " : "", + error->message); + + if (nm_utils_error_is_cancelled(error) && !nm_device_is_activating(device)) + return; + + nm_clear_g_cancellable(&priv->find_cancellable); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + return; + } + + nm_clear_g_cancellable(&priv->find_cancellable); + _LOGI(LOGD_DEVICE | LOGD_WIFI, + "%s(wifi-p2p) Target peer discovery running", + nm_device_is_activating(NM_DEVICE(self)) ? "Activation: " : ""); +} + +static void +iwd_request_discovery(NMDeviceIwdP2P *self, unsigned timeout) +{ + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + bool requested = priv->find_peer_timeout_source != NULL; + + nm_clear_g_source_inst(&priv->find_peer_timeout_source); + priv->find_peer_timeout_source = + nm_g_timeout_add_seconds_source(timeout, iwd_discovery_timeout_cb, self); + + if (!requested) { + priv->find_cancellable = g_cancellable_new(); + + g_dbus_proxy_call(priv->dbus_p2p_proxy, + "RequestDiscovery", + NULL, + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + priv->find_cancellable, + iwd_request_discovery_cb, + self); + } +} + +static void +iwd_release_discovery(NMDeviceIwdP2P *self) +{ + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + nm_clear_g_source_inst(&priv->find_peer_timeout_source); + nm_clear_g_cancellable(&priv->find_cancellable); + + g_dbus_proxy_call(priv->dbus_p2p_proxy, + "ReleaseDiscovery", + NULL, + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + NULL, + self); +} + +/* + * Called when IWD has been unable to find the peer we want to connect to within the + * 10s time limit or when a D-bus Find() ends. + */ +static gboolean +iwd_discovery_timeout_cb(gpointer user_data) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(user_data); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); + + nm_clear_g_source_inst(&priv->find_peer_timeout_source); + + iwd_release_discovery(self); + + if (nm_device_is_activating(device)) { + _LOGW(LOGD_DEVICE | LOGD_WIFI, + "Activation: (wifi-p2p) Could not find peer, failing activation"); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + } else { + _LOGD(LOGD_DEVICE | LOGD_WIFI, "(wifi-p2p) Find timeout"); + } + + return G_SOURCE_REMOVE; +} + +static void +cleanup_connect_attempt(NMDeviceIwdP2P *self) +{ + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + if (priv->find_peer_timeout_source) + iwd_release_discovery(self); + + if (priv->wfd_registered) { + nm_iwd_manager_unregister_wfd(nm_iwd_manager_get()); + priv->wfd_registered = FALSE; + } + + if (!priv->dbus_peer_proxy) + return; + + if (nm_device_is_activating(NM_DEVICE(self))) + nm_device_set_ip_iface(NM_DEVICE(self), NULL); + + priv->stage2_ready = FALSE; + g_signal_handlers_disconnect_by_data(priv->dbus_peer_proxy, self); + g_clear_object(&priv->dbus_peer_proxy); + nm_clear_g_cancellable(&priv->connect_cancellable); +} + +static void +peer_properties_changed_cb(GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidate_properties, + gpointer user_data) +{ + NMDeviceIwdP2P *self = user_data; + NMDeviceState state = nm_device_get_state(NM_DEVICE(self)); + gboolean new_bool; + const char *new_str; + + if (g_variant_lookup(changed_properties, "Connected", "b", &new_bool) && !new_bool + && state >= NM_DEVICE_STATE_CONFIG && state <= NM_DEVICE_STATE_DEACTIVATING) { + cleanup_connect_attempt(self); + nm_device_state_changed(NM_DEVICE(self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + } + + if (g_variant_lookup(changed_properties, "ConnectedInterface", "&s", &new_str) + && state >= NM_DEVICE_STATE_CONFIG && state <= NM_DEVICE_STATE_IP_CONFIG) { + nm_device_set_ip_iface(NM_DEVICE(self), new_str); + } +} + +static NMActStageReturn +act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + NMConnection *connection; + NMSettingWifiP2P *s_wifi_p2p; + NMWifiP2PPeer *peer; + GBytes *wfd_ies; + + if (!priv->enabled) { + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + connection = nm_device_get_applied_connection(NM_DEVICE(self)); + g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_wifi_p2p = + NM_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P)); + g_return_val_if_fail(s_wifi_p2p, NM_ACT_STAGE_RETURN_FAILURE); + + /* Set the WFD IEs before connecting and before peer discovery if that is needed, + * usually the WFD IEs need to actually be sent in the Probe frames before we can + * receive the peers' WFD IEs and decide whether the peer is compatible with the + * requested WFD parameters. In the current setup we only get the WFD IEs from + * the connection settings so during a normal find the client will not be getting + * any WFD information about the peers and has to decide to connect based on the + * name and device type (category + subcategory) -- assuming that the peers even + * bother to reply to probes without WFD IEs. We'll then need to redo the find + * here in PREPARE because IWD wants to see that the parameters in the peer's + * WFD IEs match those in our WFD IEs. The normal use case for IWD is that the + * WFD client registers its WFD parameters as soon as it starts and they remain + * registered during the find and then during the connect. */ + wfd_ies = nm_setting_wifi_p2p_get_wfd_ies(s_wifi_p2p); + if (wfd_ies) { + NMIwdWfdInfo wfd_info = {}; + + if (!nm_wifi_utils_parse_wfd_ies(wfd_ies, &wfd_info)) { + _LOGE(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi-p2p) Can't parse connection WFD IEs"); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (!nm_iwd_manager_check_wfd_info_compatible(nm_iwd_manager_get(), &wfd_info)) { + _LOGE(LOGD_DEVICE | LOGD_WIFI, + "Activation: (wifi-p2p) An incompatible WFD connection is active"); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (!nm_iwd_manager_register_wfd(nm_iwd_manager_get(), &wfd_info)) { + _LOGE(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi-p2p) Can't register WFD service"); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + priv->wfd_registered = TRUE; + } + + peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection, TRUE); + if (!peer) { + iwd_request_discovery(self, 10); + return NM_ACT_STAGE_RETURN_POSTPONE; + } else if (priv->find_peer_timeout_source) { + iwd_release_discovery(self); + } + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +iwd_wsc_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMDeviceIwdP2P *self = user_data; + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + NMDevice *device = NM_DEVICE(self); + + variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); + if (!variant) { + _LOGE(LOGD_DEVICE | LOGD_WIFI, + "Activation: (wifi-p2p) IWD SimpleConfiguration.PushButton/StartPin() failed: %s", + error->message); + + if (nm_utils_error_is_cancelled(error) && !nm_device_is_activating(device)) + return; + + nm_clear_g_cancellable(&priv->connect_cancellable); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return; + } + + nm_clear_g_cancellable(&priv->connect_cancellable); + _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi-p2p) IWD connection successful"); + + g_signal_connect(priv->dbus_peer_proxy, + "g-properties-changed", + G_CALLBACK(peer_properties_changed_cb), + self); + + priv->stage2_ready = TRUE; + + nm_device_activate_schedule_stage2_device_config(device, FALSE); +} + +static NMActStageReturn +act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + NMConnection *connection; + NMSettingWifiP2P *s_wifi_p2p; + NMWifiP2PPeer *peer; + gs_unref_object GDBusProxy *peer_proxy = NULL; + gs_unref_object GDBusProxy *wsc_proxy = NULL; + + if (priv->stage2_ready) + return NM_ACT_STAGE_RETURN_SUCCESS; + + if (!priv->dbus_p2p_proxy) { + cleanup_connect_attempt(self); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (nm_clear_g_source_inst(&priv->find_peer_timeout_source)) + nm_assert_not_reached(); + + connection = nm_device_get_applied_connection(device); + g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + nm_assert( + NM_IS_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P))); + + /* The prepare stage ensures that the peer has been found */ + peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection, TRUE); + if (!peer) { + cleanup_connect_attempt(self); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + s_wifi_p2p = + NM_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P)); + if (nm_setting_wifi_p2p_get_wps_method(s_wifi_p2p) + == NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) { + /* TODO: check we have the pin secret, if so use StartPin(pin) otherwise request pin, + * move to NEED_AUTH and return postpone */ + cleanup_connect_attempt(self); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + peer_proxy = nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(), + nm_wifi_p2p_peer_get_supplicant_path(peer), + NM_IWD_P2P_PEER_INTERFACE); + wsc_proxy = nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(), + nm_wifi_p2p_peer_get_supplicant_path(peer), + NM_IWD_WSC_INTERFACE); + + if (!wsc_proxy || !peer_proxy) { + cleanup_connect_attempt(self); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + g_dbus_proxy_call(wsc_proxy, + "PushButton", + NULL, + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + priv->connect_cancellable, + iwd_wsc_connect_cb, + self); + + priv->dbus_peer_proxy = g_steal_pointer(&peer_proxy); + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ + +static void +emit_signal_p2p_peer_add_remove(NMDeviceIwdP2P *device, + NMWifiP2PPeer *peer, + gboolean is_added /* or else is_removed */) +{ + nm_dbus_object_emit_signal(NM_DBUS_OBJECT(device), + &interface_info_device_wifi_p2p, + is_added ? &nm_signal_info_wifi_p2p_peer_added + : &nm_signal_info_wifi_p2p_peer_removed, + "(o)", + nm_dbus_object_get_path(NM_DBUS_OBJECT(peer))); +} + +static void +act_check_new_peer_compatible(NMDeviceIwdP2P *self, NMWifiP2PPeer *peer) +{ + NMDevice *device = NM_DEVICE(self); + NMConnection *connection; + + connection = nm_device_get_applied_connection(device); + nm_assert(NM_IS_CONNECTION(connection)); + + if (nm_wifi_p2p_peer_check_compatible(peer, connection, TRUE)) { + /* A peer for the connection was found, cancel the timeout and go to configure state. */ + iwd_release_discovery(self); + nm_device_activate_schedule_stage2_device_config(device, FALSE); + } +} + +static void +peer_add_remove(NMDeviceIwdP2P *self, + gboolean is_adding, /* or else removing */ + NMWifiP2PPeer *peer, + gboolean recheck_available_connections) +{ + NMDevice *device = NM_DEVICE(self); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + if (is_adding) { + g_object_ref(peer); + peer->wifi_device = device; + c_list_link_tail(&priv->peers_lst_head, &peer->peers_lst); + nm_dbus_object_export(NM_DBUS_OBJECT(peer)); + _peer_dump(self, LOGL_DEBUG, peer, "added", 0); + + emit_signal_p2p_peer_add_remove(self, peer, TRUE); + } else { + peer->wifi_device = NULL; + c_list_unlink(&peer->peers_lst); + _peer_dump(self, LOGL_DEBUG, peer, "removed", 0); + } + + _notify(self, PROP_PEERS); + + if (!is_adding) { + emit_signal_p2p_peer_add_remove(self, peer, FALSE); + nm_dbus_object_clear_and_unexport(&peer); + } + + if (is_adding) { + /* If we are in prepare state, then we are currently running a find + * to search for the requested peer. */ + if (priv->find_peer_timeout_source + && nm_device_get_state(device) == NM_DEVICE_STATE_PREPARE) + act_check_new_peer_compatible(self, peer); + + /* TODO: We may want to re-check auto-activation here */ + } +} + +static void +iwd_peer_interface_added_cb(GDBusObject *peer_obj, GDBusInterface *interface, gpointer user_data) +{ + NMDeviceIwdP2P *self = user_data; + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + const char *iface_name; + NMWifiP2PPeer *peer; + + g_return_if_fail(G_IS_DBUS_PROXY(interface)); + + iface_name = g_dbus_proxy_get_interface_name(G_DBUS_PROXY(interface)); + if (!nm_streq(iface_name, NM_IWD_P2P_WFD_INTERFACE)) + return; + + peer = nm_wifi_p2p_peers_find_by_supplicant_path(&priv->peers_lst_head, + g_dbus_object_get_object_path(peer_obj)); + if (!peer) + return; + + nm_wifi_p2p_peer_update_from_iwd_object(peer, peer_obj); + + /* If we are in prepare state, then we are currently running a find + * to search for the requested peer. */ + if (priv->find_peer_timeout_source) + act_check_new_peer_compatible(self, peer); +} + +static void +iwd_peer_interface_removed_cb(GDBusObject *peer_obj, GDBusInterface *interface, gpointer user_data) +{ + NMDeviceIwdP2P *self = user_data; + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + const char *iface_name; + NMWifiP2PPeer *peer; + + g_return_if_fail(G_IS_DBUS_PROXY(interface)); + + iface_name = g_dbus_proxy_get_interface_name(G_DBUS_PROXY(interface)); + if (!nm_streq(iface_name, NM_IWD_P2P_WFD_INTERFACE)) + return; + + peer = nm_wifi_p2p_peers_find_by_supplicant_path(&priv->peers_lst_head, + g_dbus_object_get_object_path(peer_obj)); + if (!peer) + return; + + nm_wifi_p2p_peer_set_wfd_ies(peer, NULL); +} + +void +nm_device_iwd_p2p_peer_add_remove(NMDeviceIwdP2P *self, GDBusObject *peer_obj, bool add) +{ + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + NMWifiP2PPeer *found_peer; + + found_peer = nm_wifi_p2p_peers_find_by_supplicant_path(&priv->peers_lst_head, + g_dbus_object_get_object_path(peer_obj)); + + if (found_peer && !add) { + if (priv->dbus_peer_proxy + && !nm_streq(g_dbus_object_get_object_path(peer_obj), + g_dbus_proxy_get_object_path(priv->dbus_peer_proxy))) { + cleanup_connect_attempt(self); + nm_device_state_changed(NM_DEVICE(self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + } + + peer_add_remove(self, FALSE, found_peer, TRUE); + g_signal_handlers_disconnect_by_data(peer_obj, self); + } + + if (!found_peer && add) { + gs_unref_object NMWifiP2PPeer *peer = nm_wifi_p2p_peer_new_from_iwd_object(peer_obj); + + if (!peer) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, + "Can't interpret IWD Peer properties at %s", + g_dbus_object_get_object_path(peer_obj)); + return; + } + + peer_add_remove(self, TRUE, peer, TRUE); + + /* None of the D-Bus properties that we use on this interface emit PropertiesChanges + * signals, only the WFD properties do. We do listen to changes to "Connected" + * but only while we're connecting/connected to a given peer. + */ + g_signal_connect(peer_obj, + "interface-added", + G_CALLBACK(iwd_peer_interface_added_cb), + self); + g_signal_connect(peer_obj, + "interface-removed", + G_CALLBACK(iwd_peer_interface_removed_cb), + self); + + /* TODO: every now and then call p2p.Device.GetPeers() and update the signal strength + * values for all peers we got through ObjectManager events. + */ + } + + schedule_peer_list_dump(self); +} + +/*****************************************************************************/ + +static void +deactivate(NMDevice *device) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + if (priv->find_peer_timeout_source) + iwd_release_discovery(self); + + if (priv->dbus_peer_proxy) { + g_dbus_proxy_call(priv->dbus_peer_proxy, + "Disconnect", + NULL, + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + NULL, + self); + + cleanup_connect_attempt(self); + } +} + +static guint32 +get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force) +{ + *out_source = NM_DEVICE_MTU_SOURCE_NONE; + return 0; +} + +static gboolean +unmanaged_on_quit(NMDevice *self) +{ + return TRUE; +} + +static void +device_state_changed(NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(device); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + switch (new_state) { + case NM_DEVICE_STATE_UNMANAGED: + break; + case NM_DEVICE_STATE_UNAVAILABLE: + if (priv->enabled) { + nm_device_queue_recheck_available(device, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } + break; + case NM_DEVICE_STATE_IP_CONFIG: + /* TODO: start periodic RSSI and bitrate updates? */ + break; + default: + break; + } +} + +static void +impl_device_iwd_p2p_start_find(NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(obj); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + gs_unref_variant GVariant *options = NULL; + const char *opts_key; + GVariant *opts_val; + GVariantIter iter; + gint32 timeout = 30; + + g_variant_get(parameters, "(@a{sv})", &options); + + g_variant_iter_init(&iter, options); + while (g_variant_iter_next(&iter, "{&sv}", &opts_key, &opts_val)) { + _nm_unused gs_unref_variant GVariant *opts_val_free = opts_val; + + if (nm_streq(opts_key, "timeout")) { + if (!g_variant_is_of_type(opts_val, G_VARIANT_TYPE_INT32)) { + g_dbus_method_invocation_return_error_literal( + invocation, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_ARGUMENT, + "\"timeout\" must be an integer \"i\""); + return; + } + + timeout = g_variant_get_int32(opts_val); + if (timeout <= 0 || timeout > 600) { + g_dbus_method_invocation_return_error_literal( + invocation, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "The timeout for a find operation needs to be in the range of 1-600s."); + return; + } + + continue; + } + + g_dbus_method_invocation_return_error(invocation, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_ARGUMENT, + "Unsupported options key \"%s\"", + opts_key); + return; + } + + if (!priv->enabled || nm_device_is_activating(NM_DEVICE(self))) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "P2P device not enabled or busy."); + return; + } + + iwd_request_discovery(self, timeout); + g_dbus_method_invocation_return_value(invocation, NULL); +} + +static void +impl_device_iwd_p2p_stop_find(NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(obj); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + if (!priv->find_peer_timeout_source || nm_device_is_activating(NM_DEVICE(self))) { + g_dbus_method_invocation_return_error_literal(invocation, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Find phase is not active."); + return; + } + + iwd_release_discovery(self); + g_dbus_method_invocation_return_value(invocation, NULL); +} + +/*****************************************************************************/ + +static bool +nm_device_iwd_p2p_set_dbus_obj(NMDeviceIwdP2P *self, GDBusObject *obj) +{ + NMDeviceIwdP2PPrivate *priv; + gs_unref_variant GVariant *enabled_value = NULL; + + g_return_val_if_fail(NM_IS_DEVICE_IWD_P2P(self), FALSE); + + priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + if (priv->dbus_obj == obj) + goto done; + + if (priv->dbus_obj) { + cleanup_connect_attempt(self); + g_signal_handlers_disconnect_by_data(priv->dbus_p2p_proxy, self); + g_clear_object(&priv->dbus_p2p_proxy); + g_clear_object(&priv->dbus_obj); + priv->enabled = FALSE; + } + + if (!obj) + goto done; + + priv->dbus_p2p_proxy = G_DBUS_PROXY(g_dbus_object_get_interface(obj, NM_IWD_P2P_INTERFACE)); + if (!priv->dbus_p2p_proxy) + return FALSE; + + enabled_value = g_dbus_proxy_get_cached_property(priv->dbus_p2p_proxy, "Enabled"); + if (!enabled_value || !g_variant_is_of_type(enabled_value, G_VARIANT_TYPE_BOOLEAN)) + return FALSE; + + priv->dbus_obj = g_object_ref(obj); + + g_signal_connect(priv->dbus_p2p_proxy, + "g-properties-changed", + G_CALLBACK(p2p_properties_changed_cb), + self); + + priv->enabled = g_variant_get_boolean(enabled_value); + _LOGD(LOGD_WIFI, "iniital state is %s", priv->enabled ? "enabled" : "disabled"); + +done: + nm_device_queue_recheck_available(NM_DEVICE(self), + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return TRUE; +} + +void +nm_device_iwd_p2p_remove(NMDeviceIwdP2P *self) +{ + g_signal_emit_by_name(self, NM_DEVICE_REMOVED); +} + +/*****************************************************************************/ + +static const char * +get_type_description(NMDevice *device) +{ + return "wifi-p2p"; +} + +/*****************************************************************************/ + +static const GDBusSignalInfo nm_signal_info_wifi_p2p_peer_added = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT( + "PeerAdded", + .args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("peer", "o"), ), ); + +static const GDBusSignalInfo nm_signal_info_wifi_p2p_peer_removed = + NM_DEFINE_GDBUS_SIGNAL_INFO_INIT( + "PeerRemoved", + .args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("peer", "o"), ), ); + +static const NMDBusInterfaceInfoExtended interface_info_device_wifi_p2p = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( + NM_DBUS_INTERFACE_DEVICE_WIFI_P2P, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS( + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED( + NM_DEFINE_GDBUS_METHOD_INFO_INIT( + "StartFind", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("options", "a{sv}"), ), ), + .handle = impl_device_iwd_p2p_start_find, ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED(NM_DEFINE_GDBUS_METHOD_INFO_INIT("StopFind", ), + .handle = impl_device_iwd_p2p_stop_find, ), ), + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_wifi_p2p_peer_added, + &nm_signal_info_wifi_p2p_peer_removed, ), + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Peers", + "ao", + NM_DEVICE_IWD_P2P_PEERS), ), ), +}; + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(object); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + const char **list; + + switch (prop_id) { + case PROP_PEERS: + list = nm_wifi_p2p_peers_get_paths(&priv->peers_lst_head); + g_value_take_boxed(value, nm_strv_make_deep_copied(list)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_device_iwd_p2p_init(NMDeviceIwdP2P *self) +{ + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(self); + + c_list_init(&priv->peers_lst_head); +} + +NMDeviceIwdP2P * +nm_device_iwd_p2p_new(GDBusObject *dbus_obj) +{ + gs_unref_object NMDeviceIwdP2P *self = NULL; + + g_return_val_if_fail(!dbus_obj || G_IS_DBUS_OBJECT(dbus_obj), NULL); + + /* cfg80211 P2P-Device virtual interfaces don't map to netdev-type interfaces. + * Provide a false unique interface name only to avoid triggering assertions + * in NMManager and for that name to appear in debug messages. */ + self = g_object_new(NM_TYPE_DEVICE_IWD_P2P, + NM_DEVICE_IFACE, + g_dbus_object_get_object_path(dbus_obj), + NM_DEVICE_TYPE_DESC, + "802.11 Wi-Fi P2P", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_WIFI_P2P, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_WIFI, + NM_DEVICE_RFKILL_TYPE, + RFKILL_TYPE_WLAN, + NULL); + + if (!self || !nm_device_iwd_p2p_set_dbus_obj(self, dbus_obj)) + return NULL; + + return nm_steal_pointer(&self); +} + +static void +dispose(GObject *object) +{ + NMDeviceIwdP2P *self = NM_DEVICE_IWD_P2P(object); + NMDeviceIwdP2PPrivate *priv = NM_DEVICE_IWD_P2P_GET_PRIVATE(object); + + nm_clear_g_source_inst(&priv->peer_dump_source); + + nm_device_iwd_p2p_set_dbus_obj(self, NULL); + + G_OBJECT_CLASS(nm_device_iwd_p2p_parent_class)->dispose(object); +} + +static void +nm_device_iwd_p2p_class_init(NMDeviceIwdP2PClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); + + object_class->get_property = get_property; + object_class->dispose = dispose; + + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_wifi_p2p); + + device_class->connection_type_supported = NM_SETTING_WIFI_P2P_SETTING_NAME; + device_class->connection_type_check_compatible = NM_SETTING_WIFI_P2P_SETTING_NAME; + device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_WIFI_P2P); + device_class->get_type_description = get_type_description; + + device_class->is_available = is_available; + device_class->check_connection_compatible = check_connection_compatible; + device_class->check_connection_available = check_connection_available; + device_class->complete_connection = complete_connection; + device_class->get_enabled = get_enabled; + device_class->set_enabled = set_enabled; + + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage2_config = act_stage2_config; + device_class->get_configured_mtu = get_configured_mtu; + + device_class->deactivate = deactivate; + device_class->unmanaged_on_quit = unmanaged_on_quit; + + device_class->state_changed = device_state_changed; + + obj_properties[PROP_PEERS] = g_param_spec_boxed(NM_DEVICE_IWD_P2P_PEERS, + "", + "", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} diff --git a/src/core/devices/wifi/nm-device-iwd-p2p.h b/src/core/devices/wifi/nm-device-iwd-p2p.h new file mode 100644 index 00000000..9ce353c0 --- /dev/null +++ b/src/core/devices/wifi/nm-device-iwd-p2p.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021 Intel Corporation + */ + +#ifndef __NM_DEVICE_IWD_P2P_H__ +#define __NM_DEVICE_IWD_P2P_H__ + +#include "devices/nm-device.h" +#include "nm-device-wifi-p2p.h" + +#define NM_TYPE_DEVICE_IWD_P2P (nm_device_iwd_p2p_get_type()) +#define NM_DEVICE_IWD_P2P(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_IWD_P2P, NMDeviceIwdP2P)) +#define NM_DEVICE_IWD_P2P_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_IWD_P2P, NMDeviceIwdP2PClass)) +#define NM_IS_DEVICE_IWD_P2P(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_IWD_P2P)) +#define NM_IS_DEVICE_IWD_P2P_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_IWD_P2P)) +#define NM_DEVICE_IWD_P2P_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_IWD_P2P, NMDeviceIwdP2PClass)) + +#define NM_DEVICE_IWD_P2P_PEERS NM_DEVICE_WIFI_P2P_PEERS +#define NM_DEVICE_IWD_P2P_GROUPS NM_DEVICE_WIFI_P2P_GROUPS + +typedef struct _NMDeviceIwdP2P NMDeviceIwdP2P; +typedef struct _NMDeviceIwdP2PClass NMDeviceIwdP2PClass; + +GType nm_device_iwd_p2p_get_type(void); + +NMDeviceIwdP2P *nm_device_iwd_p2p_new(GDBusObject *object); + +void nm_device_iwd_p2p_remove(NMDeviceIwdP2P *p2p); + +void nm_device_iwd_p2p_peer_add_remove(NMDeviceIwdP2P *p2p, GDBusObject *peer_obj, bool add); + +#endif /* __NM_DEVICE_IWD_P2P_H__ */ diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index 27a3188b..7543d9da 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -48,14 +48,14 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceIwd, PROP_LAST_SCAN, ); typedef struct { - GDBusObject * dbus_obj; - GDBusProxy * dbus_device_proxy; - GDBusProxy * dbus_station_proxy; - GDBusProxy * dbus_ap_proxy; - GDBusProxy * dbus_adhoc_proxy; + GDBusObject *dbus_obj; + GDBusProxy *dbus_device_proxy; + GDBusProxy *dbus_station_proxy; + GDBusProxy *dbus_ap_proxy; + GDBusProxy *dbus_adhoc_proxy; CList aps_lst_head; - NMWifiAP * current_ap; - GCancellable * cancellable; + NMWifiAP *current_ap; + GCancellable *cancellable; _NMDeviceWifiCapabilities capabilities; NMActRequestGetSecretsCallId *wifi_secrets_id; guint periodic_scan_id; @@ -74,8 +74,8 @@ typedef struct { uint32_t ap_id; guint32 rate; NMEtherAddr current_ap_bssid; - GDBusMethodInvocation * pending_agent_request; - NMActiveConnection * assumed_ac; + GDBusMethodInvocation *pending_agent_request; + NMActiveConnection *assumed_ac; guint assumed_ac_timeout; } NMDeviceIwdPrivate; @@ -120,7 +120,7 @@ _ap_dump(NMDeviceIwd *self, NMLogLevel log_level, const NMWifiAP *ap, const char static void ap_add_remove(NMDeviceIwd *self, gboolean is_adding, /* or else is removing */ - NMWifiAP * ap, + NMWifiAP *ap, gboolean recheck_available_connections) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); @@ -156,7 +156,7 @@ static void set_current_ap(NMDeviceIwd *self, NMWifiAP *new_ap, gboolean recheck_available_connections) { NMDeviceIwdPrivate *priv; - NMWifiAP * old_ap; + NMWifiAP *old_ap; g_return_if_fail(NM_IS_DEVICE_IWD(self)); @@ -186,7 +186,7 @@ static void remove_all_aps(NMDeviceIwd *self) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMWifiAP * ap, *ap_safe; + NMWifiAP *ap, *ap_safe; if (c_list_is_empty(&priv->aps_lst_head)) return; @@ -219,20 +219,20 @@ ap_security_flags_from_network_type(const char *type) static NMWifiAP * ap_from_network(NMDeviceIwd *self, - GDBusProxy * network, + GDBusProxy *network, NMRefString *bss_path, gint64 last_seen_msec, int16_t signal) { - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); gs_unref_variant GVariant *name_value = NULL; gs_unref_variant GVariant *type_value = NULL; - const char * name; - const char * type; + const char *name; + const char *type; uint32_t ap_id; - gs_unref_bytes GBytes *ssid = NULL; - NMWifiAP * ap; - NMSupplicantBssInfo bss_info; + gs_unref_bytes GBytes *ssid = NULL; + NMWifiAP *ap; + NMSupplicantBssInfo bss_info; g_return_val_if_fail(network, NULL); @@ -284,14 +284,14 @@ ap_from_network(NMDeviceIwd *self, static void insert_ap_from_network(NMDeviceIwd *self, - GHashTable * aps, - const char * path, + GHashTable *aps, + const char *path, gint64 last_seen_msec, int16_t signal) { - gs_unref_object GDBusProxy *network_proxy = NULL; - nm_auto_ref_string NMRefString *bss_path = nm_ref_string_new(path); - NMWifiAP * ap; + gs_unref_object GDBusProxy *network_proxy = NULL; + nm_auto_ref_string NMRefString *bss_path = nm_ref_string_new(path); + NMWifiAP *ap; if (g_hash_table_lookup(aps, bss_path)) { _LOGD(LOGD_WIFI, "Duplicate network at %s", path); @@ -311,16 +311,16 @@ insert_ap_from_network(NMDeviceIwd *self, static void get_ordered_networks_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMDeviceIwd * self = user_data; - NMDeviceIwdPrivate *priv; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *variant = NULL; - GVariantIter * networks; - const char * path; - int16_t signal; - NMWifiAP * ap, *ap_safe, *new_ap; - gboolean changed; - GHashTableIter ap_iter; + NMDeviceIwd *self = user_data; + NMDeviceIwdPrivate *priv; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *variant = NULL; + GVariantIter *networks; + const char *path; + int16_t signal; + NMWifiAP *ap, *ap_safe, *new_ap; + gboolean changed; + GHashTableIter ap_iter; gs_unref_hashtable GHashTable *new_aps = NULL; gint64 last_seen_msec; @@ -421,7 +421,7 @@ periodic_update(NMDeviceIwd *self) int percent; NMEtherAddr bssid; gboolean ap_changed = FALSE; - NMPlatform * platform; + NMPlatform *platform; ifindex = nm_device_get_ifindex(NM_DEVICE(self)); if (ifindex <= 0) @@ -528,8 +528,8 @@ cleanup_association_attempt(NMDeviceIwd *self, gboolean disconnect) } static void -reset_mode(NMDeviceIwd * self, - GCancellable * cancellable, +reset_mode(NMDeviceIwd *self, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { @@ -575,7 +575,7 @@ get_variant_state(GVariant *v) static void deactivate(NMDevice *device) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); if (!priv->dbus_obj) @@ -608,8 +608,8 @@ disconnect_cb(GObject *source, GAsyncResult *res, gpointer user_data) gs_unref_object NMDeviceIwd *self = NULL; NMDeviceDeactivateCallback callback; gpointer callback_user_data; - gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; nm_utils_user_data_unpack(user_data, &self, &callback, &callback_user_data); @@ -623,7 +623,7 @@ disconnect_cb_on_idle(gpointer user_data, GCancellable *cancellable) gs_unref_object NMDeviceIwd *self = NULL; NMDeviceDeactivateCallback callback; gpointer callback_user_data; - gs_free_error GError *cancelled_error = NULL; + gs_free_error GError *cancelled_error = NULL; nm_utils_user_data_unpack(user_data, &self, &callback, &callback_user_data); @@ -632,12 +632,12 @@ disconnect_cb_on_idle(gpointer user_data, GCancellable *cancellable) } static void -deactivate_async(NMDevice * device, - GCancellable * cancellable, +deactivate_async(NMDevice *device, + GCancellable *cancellable, NMDeviceDeactivateCallback callback, gpointer callback_user_data) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); gpointer user_data; @@ -676,7 +676,7 @@ static gboolean is_connection_known_network(NMConnection *connection) { NMIwdNetworkSecurity security; - gs_free char * ssid = NULL; + gs_free char *ssid = NULL; if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, &ssid, &security)) return FALSE; @@ -688,7 +688,7 @@ static gboolean is_ap_known_network(NMWifiAP *ap) { gs_unref_object GDBusProxy *network_proxy = NULL; - gs_unref_variant GVariant *known_network = NULL; + gs_unref_variant GVariant *known_network = NULL; network_proxy = nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(), @@ -704,17 +704,17 @@ is_ap_known_network(NMWifiAP *ap) static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); - NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMSettingWireless * s_wireless; - const char * mac; - const char *const * mac_blacklist; + NMDeviceIwd *self = NM_DEVICE_IWD(device); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMSettingWireless *s_wireless; + const char *mac; + const char *const *mac_blacklist; int i; - const char * perm_hw_addr; - const char * mode; + const char *perm_hw_addr; + const char *mode; NMIwdNetworkSecurity security; - GBytes * ssid; - const guint8 * ssid_bytes; + GBytes *ssid; + const guint8 *ssid_bytes; gsize ssid_len; if (!NM_DEVICE_CLASS(nm_device_iwd_parent_class) @@ -860,17 +860,17 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, +check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) -{ - NMDeviceIwd * self = NM_DEVICE_IWD(device); - NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMSettingWireless * s_wifi; - const char * mode; - NMWifiAP * ap = NULL; + const char *specific_object, + GError **error) +{ + NMDeviceIwd *self = NM_DEVICE_IWD(device); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMSettingWireless *s_wifi; + const char *mode; + NMWifiAP *ap = NULL; NMIwdNetworkSecurity security; s_wifi = nm_connection_get_setting_wireless(connection); @@ -952,20 +952,20 @@ iwd_ssid_to_str(const GBytes *ssid) } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMSettingWireless * s_wifi; - gs_free char * ssid_utf8 = NULL; - NMWifiAP * ap; - GBytes * ssid = NULL; + NMSettingWireless *s_wifi; + gs_free char *ssid_utf8 = NULL; + NMWifiAP *ap; + GBytes *ssid = NULL; gboolean hidden = FALSE; - const char * mode; + const char *mode; s_wifi = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_WIRELESS); @@ -1059,7 +1059,7 @@ complete_connection(NMDevice * device, static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); NMDeviceState state = nm_device_get_state(device); @@ -1088,12 +1088,12 @@ get_autoconnect_allowed(NMDevice *device) static gboolean can_auto_connect(NMDevice *device, NMSettingsConnection *sett_conn, char **specific_object) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMConnection * connection; - NMSettingWireless * s_wifi; - NMWifiAP * ap; - const char * mode; + NMConnection *connection; + NMSettingWireless *s_wifi; + NMWifiAP *ap; + const char *mode; guint64 timestamp = 0; nm_assert(!specific_object || !*specific_object); @@ -1141,10 +1141,10 @@ _nm_device_iwd_get_aps(NMDeviceIwd *self) static void scan_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMDeviceIwd * self = user_data; - NMDeviceIwdPrivate *priv; + NMDeviceIwd *self = user_data; + NMDeviceIwdPrivate *priv; gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant && nm_utils_error_is_cancelled(error)) @@ -1165,14 +1165,14 @@ scan_cb(GObject *source, GAsyncResult *res, gpointer user_data) } static void -dbus_request_scan_cb(NMDevice * device, +dbus_request_scan_cb(NMDevice *device, GDBusMethodInvocation *context, - NMAuthSubject * subject, - GError * error, + NMAuthSubject *subject, + GError *error, gpointer user_data) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); - NMDeviceIwdPrivate *priv; + NMDeviceIwd *self = NM_DEVICE_IWD(device); + NMDeviceIwdPrivate *priv; gs_unref_variant GVariant *scan_options = user_data; if (error) { @@ -1229,7 +1229,7 @@ void _nm_device_iwd_request_scan(NMDeviceIwd *self, GVariant *options, GDBusMethodInvocation *invocation) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); if (!priv->can_scan) { g_dbus_method_invocation_return_error_literal(invocation, @@ -1283,7 +1283,7 @@ static const char * get_agent_request_network_path(GDBusMethodInvocation *invocation) { const char *method_name = g_dbus_method_invocation_get_method_name(invocation); - GVariant * params = g_dbus_method_invocation_get_parameters(invocation); + GVariant *params = g_dbus_method_invocation_get_parameters(invocation); const char *network_path = NULL; if (nm_streq(method_name, "RequestPassphrase")) @@ -1308,17 +1308,17 @@ get_agent_request_network_path(GDBusMethodInvocation *invocation) * Return TRUE in either case, return FALSE if an error is detected. */ static gboolean -try_reply_agent_request(NMDeviceIwd * self, - NMConnection * connection, +try_reply_agent_request(NMDeviceIwd *self, + NMConnection *connection, GDBusMethodInvocation *invocation, gboolean allow_existing, - const char ** setting_name, - const char ** setting_key, - gboolean * replied) + const char **setting_name, + const char **setting_key, + gboolean *replied) { - const char * method_name = g_dbus_method_invocation_get_method_name(invocation); + const char *method_name = g_dbus_method_invocation_get_method_name(invocation); NMSettingWirelessSecurity *s_wireless_sec; - NMSetting8021x * s_8021x; + NMSetting8021x *s_8021x; s_wireless_sec = nm_connection_get_setting_wireless_security(connection); s_8021x = nm_connection_get_setting_802_1x(connection); @@ -1418,7 +1418,7 @@ try_reply_agent_request(NMDeviceIwd * self, static gboolean assumed_ac_timeout_cb(gpointer user_data) { - NMDeviceIwd * self = user_data; + NMDeviceIwd *self = user_data; NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); nm_assert(priv->assumed_ac); @@ -1434,30 +1434,30 @@ assumed_ac_timeout_cb(gpointer user_data) return G_SOURCE_REMOVE; } -static void wifi_secrets_get_one(NMDeviceIwd * self, - const char * setting_name, +static void wifi_secrets_get_one(NMDeviceIwd *self, + const char *setting_name, NMSecretAgentGetSecretsFlags flags, - const char * setting_key, - GDBusMethodInvocation * invocation); + const char *setting_key, + GDBusMethodInvocation *invocation); static void -wifi_secrets_cb(NMActRequest * req, +wifi_secrets_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * s_connection, - GError * error, + NMSettingsConnection *s_connection, + GError *error, gpointer user_data) { - NMDeviceIwd * self; - NMDeviceIwdPrivate * priv; - NMDevice * device; - GDBusMethodInvocation * invocation; - const char * setting_name; - const char * setting_key; + NMDeviceIwd *self; + NMDeviceIwdPrivate *priv; + NMDevice *device; + GDBusMethodInvocation *invocation; + const char *setting_name; + const char *setting_key; gboolean replied; NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; NMIwdNetworkSecurity security; - NMConnection * connection; + NMConnection *connection; nm_utils_user_data_unpack(user_data, &self, &invocation); @@ -1550,14 +1550,14 @@ secrets_error: } static void -wifi_secrets_get_one(NMDeviceIwd * self, - const char * setting_name, +wifi_secrets_get_one(NMDeviceIwd *self, + const char *setting_name, NMSecretAgentGetSecretsFlags flags, - const char * setting_key, - GDBusMethodInvocation * invocation) + const char *setting_key, + GDBusMethodInvocation *invocation) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMActRequest * req; + NMActRequest *req; wifi_secrets_cancel(self); @@ -1576,16 +1576,16 @@ wifi_secrets_get_one(NMDeviceIwd * self, static void network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMDeviceIwd * self = user_data; - NMDevice * device = NM_DEVICE(self); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDeviceIwd *self = user_data; + NMDevice *device = NM_DEVICE(self); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - NMConnection * connection; - gs_free char * ssid = NULL; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED; - GVariant * value; - gboolean disconnect; + gs_free_error GError *error = NULL; + NMConnection *connection; + gs_free char *ssid = NULL; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED; + GVariant *value; + gboolean disconnect; disconnect = !priv->iwd_autoconnect || nm_device_autoconnect_blocked_get(device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL); @@ -1642,7 +1642,7 @@ network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Connected to '%s'.", ssid); - nm_device_activate_schedule_stage3_ip_config_start(device); + nm_device_activate_schedule_stage3_ip_config(device, FALSE); return; @@ -1667,10 +1667,10 @@ failed: static void act_failed_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMDeviceIwd * self = user_data; - NMDevice * device = NM_DEVICE(self); + NMDeviceIwd *self = user_data; + NMDevice *device = NM_DEVICE(self); gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant && nm_utils_error_is_cancelled(error)) @@ -1689,12 +1689,12 @@ act_failed_cb(GObject *source, GAsyncResult *res, gpointer user_data) static void act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMDeviceIwd * self = user_data; - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDeviceIwd *self = user_data; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; - gs_free char * ssid = NULL; + gs_free_error GError *error = NULL; + gs_free char *ssid = NULL; variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant) { @@ -1721,7 +1721,7 @@ act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data) _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Started '%s'.", ssid); - nm_device_activate_schedule_stage3_ip_config_start(device); + nm_device_activate_schedule_stage3_ip_config(device, FALSE); return; @@ -1736,12 +1736,12 @@ error: static void act_check_interface(NMDeviceIwd *self) { - NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - NMSettingWireless * s_wireless; - GDBusProxy * proxy = NULL; - gs_free char * ssid = NULL; - const char * mode; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); + NMSettingWireless *s_wireless; + GDBusProxy *proxy = NULL; + gs_free char *ssid = NULL; + const char *mode; NMIwdNetworkSecurity security; if (!priv->act_mode_switch) @@ -1780,7 +1780,7 @@ act_check_interface(NMDeviceIwd *self) self); } else if (security == NM_IWD_NETWORK_SECURITY_PSK) { NMSettingWirelessSecurity *s_wireless_sec; - const char * psk; + const char *psk; s_wireless_sec = (NMSettingWirelessSecurity *) nm_device_get_applied_setting( device, @@ -1813,11 +1813,11 @@ failed: static void act_set_mode_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMDeviceIwd * self = user_data; - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDeviceIwd *self = user_data; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant) { @@ -1848,10 +1848,10 @@ static void act_set_mode(NMDeviceIwd *self) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - const char * iwd_mode; - const char * mode; - NMSettingWireless * s_wireless; + NMDevice *device = NM_DEVICE(self); + const char *iwd_mode; + const char *mode; + NMSettingWireless *s_wireless; s_wireless = (NMSettingWireless *) nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS); @@ -1880,15 +1880,15 @@ act_set_mode(NMDeviceIwd *self) } static void -act_psk_cb(NMActRequest * req, +act_psk_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * s_connection, - GError * error, + NMSettingsConnection *s_connection, + GError *error, gpointer user_data) { - NMDeviceIwd * self = user_data; + NMDeviceIwd *self = user_data; NMDeviceIwdPrivate *priv; - NMDevice * device; + NMDevice *device; if (nm_utils_error_is_cancelled(error)) return; @@ -1944,7 +1944,7 @@ static NMWifiAP * find_ap_by_supplicant_path(NMDeviceIwd *self, const NMRefString *path) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMWifiAP * tmp; + NMWifiAP *tmp; c_list_for_each_entry (tmp, &priv->aps_lst_head, aps_lst) if (nm_wifi_ap_get_supplicant_path(tmp) == path) @@ -1956,7 +1956,7 @@ find_ap_by_supplicant_path(NMDeviceIwd *self, const NMRefString *path) static void assumed_connection_state_changed(NMActiveConnection *active, GParamSpec *pspec, NMDeviceIwd *self) { - NMSettingsConnection * sett_conn = nm_active_connection_get_settings_connection(active); + NMSettingsConnection *sett_conn = nm_active_connection_get_settings_connection(active); NMActiveConnectionState state = nm_active_connection_get_state(active); /* Delete the temporary connection created for an external IWD connection @@ -1983,10 +1983,10 @@ assumed_connection_state_changed(NMActiveConnection *active, GParamSpec *pspec, static void assumed_connection_state_changed_before_managed(NMActiveConnection *active, - GParamSpec * pspec, - NMDeviceIwd * self) + GParamSpec *pspec, + NMDeviceIwd *self) { - NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); NMActiveConnectionState state = nm_active_connection_get_state(active); gboolean disconnect; @@ -2020,11 +2020,11 @@ assumed_connection_state_changed_before_managed(NMActiveConnection *active, static void assume_connection(NMDeviceIwd *self, NMWifiAP *ap) { - NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMSettingsConnection *sett_conn; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMSettingsConnection *sett_conn; gs_unref_object NMAuthSubject *subject = NULL; - NMActiveConnection * ac; - gs_free_error GError *error = NULL; + NMActiveConnection *ac; + gs_free_error GError *error = NULL; /* We can use the .update_connection / nm_device_emit_recheck_assume * API but we can also pass an assumed/external activation type @@ -2104,7 +2104,7 @@ static void assumed_connection_progress_to_ip_config(NMDeviceIwd *self, gboolean was_postponed) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceState dev_state = nm_device_get_state(device); wifi_secrets_cancel(self); @@ -2127,17 +2127,17 @@ assumed_connection_progress_to_ip_config(NMDeviceIwd *self, gboolean was_postpon * that stage2 is done. */ if (was_postponed) - nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self)); + nm_device_activate_schedule_stage3_ip_config(NM_DEVICE(self), FALSE); } static void initial_check_assume(NMDeviceIwd *self) { - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - const char * network_path_str; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + const char *network_path_str; nm_auto_ref_string NMRefString *network_path = NULL; - NMWifiAP * ap = NULL; - gs_unref_variant GVariant *state_value = + NMWifiAP *ap = NULL; + gs_unref_variant GVariant *state_value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); gs_unref_variant GVariant *cn_value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "ConnectedNetwork"); @@ -2174,15 +2174,15 @@ initial_check_assume(NMDeviceIwd *self) static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMWifiAP * ap = NULL; + NMDeviceIwd *self = NM_DEVICE_IWD(device); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMWifiAP *ap = NULL; gs_unref_object NMWifiAP *ap_fake = NULL; - NMActRequest * req; - NMConnection * connection; - NMSettingWireless * s_wireless; - const char * mode; - const char * ap_path; + NMActRequest *req; + NMConnection *connection; + NMSettingWireless *s_wireless; + const char *mode; + const char *ap_path; req = nm_device_get_act_request(device); g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); @@ -2246,12 +2246,12 @@ add_new: static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMActRequest * req; - NMConnection * connection; - NMSettingWireless * s_wireless; - const char * mode; + NMActRequest *req; + NMConnection *connection; + NMSettingWireless *s_wireless; + const char *mode; req = nm_device_get_act_request(device); connection = nm_act_request_get_applied_connection(req); @@ -2262,8 +2262,8 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) if (NM_IN_STRSET(mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) { gs_unref_object GDBusProxy *network_proxy = NULL; - NMWifiAP * ap = priv->current_ap; - NMSettingWirelessSecurity * s_wireless_sec; + NMWifiAP *ap = priv->current_ap; + NMSettingWirelessSecurity *s_wireless_sec; if (!ap) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); @@ -2432,7 +2432,7 @@ get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *ou static gboolean periodic_scan_timeout_cb(gpointer user_data) { - NMDeviceIwd * self = user_data; + NMDeviceIwd *self = user_data; NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); priv->periodic_scan_id = 0; @@ -2503,15 +2503,15 @@ set_can_scan(NMDeviceIwd *self, gboolean can_scan) } static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMSettingWireless * s_wireless; - const char * mode; + NMSettingWireless *s_wireless; + const char *mode; switch (new_state) { case NM_DEVICE_STATE_UNMANAGED: @@ -2559,7 +2559,7 @@ get_enabled(NMDevice *device) static void set_enabled(NMDevice *device, gboolean enabled) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwd *self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); NMDeviceState state; @@ -2596,12 +2596,12 @@ set_enabled(NMDevice *device, gboolean enabled) } static gboolean -can_reapply_change(NMDevice * device, +can_reapply_change(NMDevice *device, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { NMDeviceClass *device_class; @@ -2624,9 +2624,9 @@ can_reapply_change(NMDevice * device, static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceIwd * self = NM_DEVICE_IWD(object); + NMDeviceIwd *self = NM_DEVICE_IWD(object); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - const char ** list; + const char **list; switch (prop_id) { case PROP_MODE: @@ -2673,18 +2673,18 @@ static void state_changed(NMDeviceIwd *self, const char *new_state) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceState dev_state = nm_device_get_state(device); gboolean nm_connection = priv->current_ap || priv->assumed_ac; gboolean iwd_connection = FALSE; - NMWifiAP * ap = NULL; + NMWifiAP *ap = NULL; gboolean can_connect = priv->nm_autoconnect; _LOGI(LOGD_DEVICE | LOGD_WIFI, "new IWD device state is %s", new_state); if (NM_IN_STRSET(new_state, "connecting", "connected", "roaming")) { - gs_unref_variant GVariant *value = NULL; - const char * network_path_str; + gs_unref_variant GVariant *value = NULL; + const char *network_path_str; nm_auto_ref_string NMRefString *network_path = NULL; value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "ConnectedNetwork"); @@ -2855,12 +2855,12 @@ scanning_changed(NMDeviceIwd *self, gboolean new_scanning) static void station_properties_changed(GDBusProxy *proxy, - GVariant * changed_properties, + GVariant *changed_properties, GStrv invalidate_properties, gpointer user_data) { NMDeviceIwd *self = user_data; - const char * new_str; + const char *new_str; gboolean new_bool; if (g_variant_lookup(changed_properties, "State", "&s", &new_str)) @@ -2872,7 +2872,7 @@ station_properties_changed(GDBusProxy *proxy, static void ap_adhoc_properties_changed(GDBusProxy *proxy, - GVariant * changed_properties, + GVariant *changed_properties, GStrv invalidate_properties, gpointer user_data) { @@ -2889,7 +2889,7 @@ static void powered_changed(NMDeviceIwd *self, gboolean new_powered) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - GDBusInterface * interface; + GDBusInterface *interface; nm_device_queue_recheck_available(NM_DEVICE(self), NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, @@ -3004,7 +3004,7 @@ powered_changed(NMDeviceIwd *self, gboolean new_powered) static void device_properties_changed(GDBusProxy *proxy, - GVariant * changed_properties, + GVariant *changed_properties, GStrv invalidate_properties, gpointer user_data) { @@ -3016,11 +3016,11 @@ device_properties_changed(GDBusProxy *proxy, } static void -config_changed(NMConfig * config, - NMConfigData * config_data, +config_changed(NMConfig *config, + NMConfigData *config_data, NMConfigChangeFlags changes, - NMConfigData * old_data, - NMDeviceIwd * self) + NMConfigData *old_data, + NMDeviceIwd *self) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); gboolean old_iwd_ac = priv->iwd_autoconnect; @@ -3048,12 +3048,12 @@ config_changed(NMConfig * config, void nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object) { - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - GDBusInterface * interface; - gs_unref_variant GVariant *value = NULL; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + GDBusInterface *interface; + gs_unref_variant GVariant *value = NULL; gs_unref_object GDBusProxy *adapter_proxy = NULL; - GVariantIter * iter; - const char * mode; + GVariantIter *iter; + const char *mode; gboolean powered; _NMDeviceWifiCapabilities capabilities; @@ -3159,18 +3159,18 @@ error: gboolean nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation) { - NMDevice * device = NM_DEVICE(self); - NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); NMDeviceState state = nm_device_get_state(device); - const char * setting_name; - const char * setting_key; + const char *setting_name; + const char *setting_key; gboolean replied; - NMWifiAP * ap; + NMWifiAP *ap; gboolean allow_existing = FALSE; NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; - NMIwdNetworkSecurity security; - NMConnection * connection; + NMIwdNetworkSecurity security; + NMConnection *connection; nm_auto_ref_string NMRefString *network_path = NULL; if (!invocation) { @@ -3324,9 +3324,9 @@ nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation) void nm_device_iwd_network_add_remove(NMDeviceIwd *self, GDBusProxy *network, bool add) { - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMWifiAP * ap = NULL; - bool recheck; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMWifiAP *ap = NULL; + bool recheck; nm_auto_ref_string NMRefString *bss_path = NULL; bss_path = nm_ref_string_new(g_dbus_proxy_get_object_path(network)); @@ -3371,7 +3371,7 @@ nm_device_iwd_network_add_remove(NMDeviceIwd *self, GDBusProxy *network, bool ad static void autoconnect_changed(NMDevice *device, GParamSpec *pspec, NMDeviceIwd *self) { - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); gs_unref_variant GVariant *value = NULL; /* Note IWD normally remains in "disconnected" during a secret request @@ -3434,7 +3434,7 @@ nm_device_iwd_new(const char *iface) static void dispose(GObject *object) { - NMDeviceIwd * self = NM_DEVICE_IWD(object); + NMDeviceIwd *self = NM_DEVICE_IWD(object); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); nm_clear_g_cancellable(&priv->cancellable); @@ -3450,9 +3450,9 @@ dispose(GObject *object) static void nm_device_iwd_class_init(NMDeviceIwdClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; object_class->dispose = dispose; diff --git a/src/core/devices/wifi/nm-device-iwd.h b/src/core/devices/wifi/nm-device-iwd.h index ce94c9ea..bb136bf6 100644 --- a/src/core/devices/wifi/nm-device-iwd.h +++ b/src/core/devices/wifi/nm-device-iwd.h @@ -40,8 +40,8 @@ gboolean nm_device_iwd_agent_query(NMDeviceIwd *device, GDBusMethodInvocation *i const CList *_nm_device_iwd_get_aps(NMDeviceIwd *self); -void _nm_device_iwd_request_scan(NMDeviceIwd * self, - GVariant * options, +void _nm_device_iwd_request_scan(NMDeviceIwd *self, + GVariant *options, GDBusMethodInvocation *invocation); void nm_device_iwd_network_add_remove(NMDeviceIwd *device, GDBusProxy *network, bool add); diff --git a/src/core/devices/wifi/nm-device-olpc-mesh.c b/src/core/devices/wifi/nm-device-olpc-mesh.c index d829f9ae..fd851ebc 100644 --- a/src/core/devices/wifi/nm-device-olpc-mesh.c +++ b/src/core/devices/wifi/nm-device-olpc-mesh.c @@ -39,7 +39,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceOlpcMesh, PROP_COMPANION, PROP_ACTIVE_CHANNEL, ); typedef struct { - NMDevice * companion; + NMDevice *companion; NMManager *manager; bool stage1_waiting : 1; } NMDeviceOlpcMeshPrivate; @@ -63,7 +63,7 @@ G_DEFINE_TYPE(NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) static gboolean get_autoconnect_allowed(NMDevice *device) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(device); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(device); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); /* We can't even connect if we don't have a companion yet. */ @@ -81,11 +81,11 @@ get_autoconnect_allowed(NMDevice *device) #define DEFAULT_SSID "olpc-mesh" static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMSettingOlpcMesh *s_mesh; @@ -133,7 +133,7 @@ get_dhcp_anycast_address(NMDevice *device) static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(device); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(device); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); /* disconnect companion device, if it is connected */ @@ -183,9 +183,9 @@ _mesh_set_channel(NMDeviceOlpcMesh *self, guint32 channel) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(device); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(device); NMSettingOlpcMesh *s_mesh; - GBytes * ssid; + GBytes *ssid; gboolean success; s_mesh = nm_device_get_applied_setting(device, NM_TYPE_SETTING_OLPC_MESH); @@ -243,7 +243,7 @@ companion_cleanup(NMDeviceOlpcMesh *self) static void companion_notify_cb(NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_data) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(user_data); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(user_data); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); nm_assert(NM_IS_DEVICE_WIFI(companion)); @@ -260,7 +260,7 @@ companion_notify_cb(NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_da /* disconnect from mesh if someone starts using the companion */ static void -companion_state_changed_cb(NMDeviceWifi * companion, +companion_state_changed_cb(NMDeviceWifi *companion, NMDeviceState state, NMDeviceState old_state, NMDeviceStateReason reason, @@ -299,7 +299,7 @@ static gboolean check_companion(NMDeviceOlpcMesh *self, NMDevice *other) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); - const char * my_addr, *their_addr; + const char *my_addr, *their_addr; if (!NM_IS_DEVICE_WIFI(other)) return FALSE; @@ -337,7 +337,7 @@ check_companion(NMDeviceOlpcMesh *self, NMDevice *other) static void device_added_cb(NMManager *manager, NMDevice *other, gpointer user_data) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(user_data); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(user_data); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); if (!priv->companion && check_companion(self, other)) { @@ -363,8 +363,8 @@ static void find_companion(NMDeviceOlpcMesh *self) { NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); - const CList * tmp_lst; - NMDevice * candidate; + const CList *tmp_lst; + NMDevice *candidate; if (priv->companion) return; @@ -386,12 +386,12 @@ find_companion(NMDeviceOlpcMesh *self) } static void -state_changed(NMDevice * device, +state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(device); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(device); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); if (new_state == NM_DEVICE_STATE_UNAVAILABLE) @@ -422,8 +422,8 @@ get_dhcp_timeout_for_device(NMDevice *device, int addr_family) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(object); - NMDevice * device = NM_DEVICE(self); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(object); + NMDevice *device = NM_DEVICE(self); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); switch (prop_id) { @@ -450,7 +450,7 @@ nm_device_olpc_mesh_init(NMDeviceOlpcMesh *self) static void constructed(GObject *object) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(object); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(object); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); G_OBJECT_CLASS(nm_device_olpc_mesh_parent_class)->constructed(object); @@ -479,7 +479,7 @@ nm_device_olpc_mesh_new(const char *iface) static void dispose(GObject *object) { - NMDeviceOlpcMesh * self = NM_DEVICE_OLPC_MESH(object); + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH(object); NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE(self); companion_cleanup(self); @@ -510,9 +510,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_olpc_mesh = { static void nm_device_olpc_mesh_class_init(NMDeviceOlpcMeshClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructed = constructed; object_class->get_property = get_property; diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index 67202a67..dfbf8978 100644 --- a/src/core/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -14,18 +14,18 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" -#include "nm-act-request.h" #include "libnm-core-aux-intern/nm-libnm-core-utils.h" #include "libnm-core-intern/nm-core-internal.h" #include "libnm-glib-aux/nm-ref-string.h" -#include "nm-ip4-config.h" +#include "libnm-platform/nm-platform.h" +#include "libnm-platform/nmp-object.h" +#include "nm-act-request.h" +#include "nm-l3-config-data.h" #include "nm-manager.h" #include "nm-manager.h" #include "nm-setting-wifi-p2p.h" #include "nm-utils.h" #include "nm-wifi-p2p-peer.h" -#include "libnm-platform/nm-platform.h" -#include "libnm-platform/nmp-object.h" #include "settings/nm-settings.h" #define _NMLOG_DEVICE_TYPE NMDeviceWifiP2P @@ -82,10 +82,10 @@ static void supplicant_interfaces_release(NMDeviceWifiP2P *self, gboolean set_is /*****************************************************************************/ static void -_peer_dump(NMDeviceWifiP2P * self, +_peer_dump(NMDeviceWifiP2P *self, NMLogLevel log_level, const NMWifiP2PPeer *peer, - const char * prefix, + const char *prefix, gint32 now_s) { char buf[1024]; @@ -100,7 +100,7 @@ _peer_dump(NMDeviceWifiP2P * self, static gboolean peer_list_dump(gpointer user_data) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(user_data); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(user_data); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); priv->peer_dump_id = 0; @@ -153,10 +153,10 @@ static gboolean check_connection_peer_joined(NMDeviceWifiP2P *device) { NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device); - NMConnection * conn = nm_device_get_applied_connection(NM_DEVICE(device)); - NMWifiP2PPeer * peer; - const char * group; - const char *const * groups; + NMConnection *conn = nm_device_get_applied_connection(NM_DEVICE(device)); + NMWifiP2PPeer *peer; + const char *group; + const char *const *groups; if (!conn || !priv->group_iface) return FALSE; @@ -168,7 +168,7 @@ check_connection_peer_joined(NMDeviceWifiP2P *device) return FALSE; /* NOTE: We currently only support connections to a specific peer */ - peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, conn); + peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, conn, FALSE); if (!peer) return FALSE; @@ -182,8 +182,8 @@ check_connection_peer_joined(NMDeviceWifiP2P *device) static gboolean disconnect_on_connection_peer_missing_cb(gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); _LOGW(LOGD_WIFI, "Peer requested in connection is missing for too long, failing connection."); @@ -222,8 +222,8 @@ update_disconnect_on_connection_peer_missing(NMDeviceWifiP2P *self) static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); - NMDeviceWifiP2PPrivate * priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); + NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); NMSupplicantInterfaceState supplicant_state; if (!priv->mgmt_iface) @@ -251,17 +251,17 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); - gs_free char * setting_name = NULL; + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); + gs_free char *setting_name = NULL; NMSettingWifiP2P *s_wifi_p2p; - NMWifiP2PPeer * peer; - const char * setting_peer; + NMWifiP2PPeer *peer; + const char *setting_peer; s_wifi_p2p = NM_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P)); @@ -329,8 +329,8 @@ complete_connection(NMDevice * device, static gboolean supplicant_find_timeout_cb(gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(user_data); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(user_data); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); priv->find_peer_timeout_id = 0; @@ -351,11 +351,11 @@ supplicant_find_timeout_cb(gpointer user_data) static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); - NMConnection * connection; - NMSettingWifiP2P * s_wifi_p2p; - NMWifiP2PPeer * peer; + NMConnection *connection; + NMSettingWifiP2P *s_wifi_p2p; + NMWifiP2PPeer *peer; if (!priv->mgmt_iface) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); @@ -369,7 +369,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) NM_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P)); g_return_val_if_fail(s_wifi_p2p, NM_ACT_STAGE_RETURN_FAILURE); - peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection); + peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection, FALSE); if (!peer) { /* Set up a timeout on the find attempt and run a find for the same period of time */ if (priv->find_peer_timeout_id == 0) { @@ -393,8 +393,8 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static gboolean supplicant_connection_timeout_cb(gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(user_data); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(user_data); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); priv->sup_timeout_id = 0; @@ -415,12 +415,12 @@ supplicant_connection_timeout_cb(gpointer user_data) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); - NMConnection * connection; - NMSettingWifiP2P * s_wifi_p2p; - NMWifiP2PPeer * peer; - GBytes * wfd_ies; + NMConnection *connection; + NMSettingWifiP2P *s_wifi_p2p; + NMWifiP2PPeer *peer; + GBytes *wfd_ies; if (nm_clear_g_source(&priv->find_peer_timeout_id)) nm_assert_not_reached(); @@ -436,7 +436,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) NM_IS_SETTING_WIFI_P2P(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIFI_P2P))); /* The prepare stage ensures that the peer has been found */ - peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection); + peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection, FALSE); if (!peer) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); return NM_ACT_STAGE_RETURN_FAILURE; @@ -469,7 +469,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) static void emit_signal_p2p_peer_add_remove(NMDeviceWifiP2P *device, - NMWifiP2PPeer * peer, + NMWifiP2PPeer *peer, gboolean is_added /* or else is_removed */) { nm_dbus_object_emit_signal(NM_DBUS_OBJECT(device), @@ -483,10 +483,10 @@ emit_signal_p2p_peer_add_remove(NMDeviceWifiP2P *device, static void peer_add_remove(NMDeviceWifiP2P *self, gboolean is_adding, /* or else removing */ - NMWifiP2PPeer * peer, + NMWifiP2PPeer *peer, gboolean recheck_available_connections) { - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); if (is_adding) { @@ -521,7 +521,8 @@ peer_add_remove(NMDeviceWifiP2P *self, connection = nm_device_get_applied_connection(device); nm_assert(NM_IS_CONNECTION(connection)); - peer = nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection); + peer = + nm_wifi_p2p_peers_find_first_compatible(&priv->peers_lst_head, connection, FALSE); if (peer) { /* A peer for the connection was found, cancel the timeout and go to configure state. */ nm_clear_g_source(&priv->find_peer_timeout_id); @@ -539,7 +540,7 @@ static void remove_all_peers(NMDeviceWifiP2P *self) { NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); - NMWifiP2PPeer * peer; + NMWifiP2PPeer *peer; if (c_list_is_empty(&priv->peers_lst_head)) return; @@ -552,46 +553,44 @@ remove_all_peers(NMDeviceWifiP2P *self) /*****************************************************************************/ -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static void +act_stage3_ip_config(NMDevice *device, int addr_family) { - NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device); + NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device); + const int IS_IPv4 = NM_IS_IPv4(addr_family); gboolean indicate_addressing_running; - NMConnection * connection; - const char * method; + NMConnection *connection; + const char *method; connection = nm_device_get_applied_connection(device); method = nm_utils_get_ip_config_method(connection, addr_family); /* We may have an address assigned by the group owner */ - if (NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) && priv->group_iface + if (IS_IPv4 && NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) && priv->group_iface && !nm_supplicant_interface_get_p2p_group_owner(priv->group_iface)) { in_addr_t addr; guint8 plen; if (nm_supplicant_interface_get_p2p_assigned_addr(priv->group_iface, &addr, &plen)) { - NMPlatformIP4Address address = { - .addr_source = NM_IP_CONFIG_SOURCE_DHCP, + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + NMPlatformIP4Address address = { + .addr_source = NM_IP_CONFIG_SOURCE_DHCP, }; - gs_unref_object NMIP4Config *ip4_config = NULL; nm_platform_ip4_address_set_addr(&address, addr, plen); - ip4_config = nm_device_ip4_config_new(device); - nm_ip4_config_add_address(ip4_config, &address); + l3cd = nm_device_create_l3_config_data(device, NM_IP_CONFIG_SOURCE_DHCP); + nm_l3_config_data_add_address_4(l3cd, &address); - nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG(ip4_config)); + nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, l3cd); /* This just disables the addressing indicator. */ method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; } } - if (addr_family == AF_INET) + if (IS_IPv4) indicate_addressing_running = NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO); else { indicate_addressing_running = NM_IN_STRSET(method, @@ -603,15 +602,12 @@ act_stage3_ip_config_start(NMDevice * device, nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), TRUE); - - return NM_DEVICE_CLASS(nm_device_wifi_p2p_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); } static void deactivate(NMDevice *device) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); int ifindex = nm_device_get_ip_ifindex(device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); @@ -642,7 +638,7 @@ get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *ou static const char * get_auto_ip_config_method(NMDevice *device, int addr_family) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); if (addr_family == AF_INET && priv->group_iface @@ -675,8 +671,8 @@ supplicant_iface_state_cb(NMSupplicantInterface *iface, int disconnect_reason, gpointer user_data) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(user_data); - NMDevice * device = NM_DEVICE(self); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(user_data); + NMDevice *device = NM_DEVICE(self); NMSupplicantInterfaceState new_state = new_state_i; NMSupplicantInterfaceState old_state = old_state_i; @@ -704,12 +700,12 @@ supplicant_iface_state_cb(NMSupplicantInterface *iface, static void supplicant_iface_peer_changed_cb(NMSupplicantInterface *iface, - NMSupplicantPeerInfo * peer_info, + NMSupplicantPeerInfo *peer_info, gboolean is_present, - NMDeviceWifiP2P * self) + NMDeviceWifiP2P *self) { NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); - NMWifiP2PPeer * found_peer; + NMWifiP2PPeer *found_peer; found_peer = nm_wifi_p2p_peers_find_by_supplicant_path(&priv->peers_lst_head, peer_info->peer_path->str); @@ -757,7 +753,7 @@ check_group_iface_ready(NMDeviceWifiP2P *self) nm_clear_g_source(&priv->sup_timeout_id); update_disconnect_on_connection_peer_missing(self); - nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self)); + nm_device_activate_schedule_stage3_ip_config(NM_DEVICE(self), FALSE); } static void @@ -786,7 +782,7 @@ supplicant_group_iface_state_cb(NMSupplicantInterface *iface, int disconnect_reason, gpointer user_data) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(user_data); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(user_data); NMSupplicantInterfaceState new_state = new_state_i; NMSupplicantInterfaceState old_state = old_state_i; @@ -812,8 +808,8 @@ supplicant_group_iface_state_cb(NMSupplicantInterface *iface, static void supplicant_group_iface_group_finished_cb(NMSupplicantInterface *iface, - const char * iface_path, - void * user_data) + const char *iface_path, + void *user_data) { NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(user_data); @@ -826,8 +822,8 @@ supplicant_group_iface_group_finished_cb(NMSupplicantInterface *iface, static void supplicant_iface_group_joined_updated_cb(NMSupplicantInterface *iface, - GParamSpec * pspec, - void * user_data) + GParamSpec *pspec, + void *user_data) { NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(user_data); @@ -837,9 +833,9 @@ supplicant_iface_group_joined_updated_cb(NMSupplicantInterface *iface, static void supplicant_iface_group_started_cb(NMSupplicantInterface *iface, NMSupplicantInterface *group_iface, - NMDeviceWifiP2P * self) + NMDeviceWifiP2P *self) { - NMDeviceWifiP2PPrivate * priv; + NMDeviceWifiP2PPrivate *priv; NMSupplicantInterfaceState state; g_return_if_fail(self); @@ -923,12 +919,12 @@ supplicant_interfaces_release(NMDeviceWifiP2P *self, gboolean set_is_waiting) } static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(device); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(device); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); update_disconnect_on_connection_peer_missing(self); @@ -984,19 +980,19 @@ device_state_changed(NMDevice * device, } static void -impl_device_wifi_p2p_start_find(NMDBusObject * obj, +impl_device_wifi_p2p_start_find(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(obj); - NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(obj); + NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); gs_unref_variant GVariant *options = NULL; - const char * opts_key; - GVariant * opts_val; + const char *opts_key; + GVariant *opts_val; GVariantIter iter; gint32 timeout = 30; @@ -1052,15 +1048,15 @@ impl_device_wifi_p2p_start_find(NMDBusObject * obj, } static void -impl_device_wifi_p2p_stop_find(NMDBusObject * obj, +impl_device_wifi_p2p_stop_find(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(obj); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(obj); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); if (!priv->mgmt_iface) { @@ -1184,9 +1180,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_wifi_p2p = { static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(object); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(object); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(self); - const char ** list; + const char **list; switch (prop_id) { case PROP_PEERS: @@ -1241,7 +1237,7 @@ nm_device_wifi_p2p_new(const char *iface) static void dispose(GObject *object) { - NMDeviceWifiP2P * self = NM_DEVICE_WIFI_P2P(object); + NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P(object); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(object); g_clear_object(&priv->sup_mgr); @@ -1254,7 +1250,7 @@ dispose(GObject *object) static void finalize(GObject *object) { - NMDeviceWifiP2P * peer = NM_DEVICE_WIFI_P2P(object); + NMDeviceWifiP2P *peer = NM_DEVICE_WIFI_P2P(object); NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(peer); nm_assert(c_list_is_empty(&priv->peers_lst_head)); @@ -1265,9 +1261,9 @@ finalize(GObject *object) static void nm_device_wifi_p2p_class_init(NMDeviceWifiP2PClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructed = constructed; object_class->get_property = get_property; @@ -1286,11 +1282,11 @@ nm_device_wifi_p2p_class_init(NMDeviceWifiP2PClass *klass) device_class->check_connection_compatible = check_connection_compatible; device_class->complete_connection = complete_connection; - device_class->act_stage1_prepare = act_stage1_prepare; - device_class->act_stage2_config = act_stage2_config; - device_class->get_configured_mtu = get_configured_mtu; - device_class->get_auto_ip_config_method = get_auto_ip_config_method; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage2_config = act_stage2_config; + device_class->get_configured_mtu = get_configured_mtu; + device_class->get_auto_ip_config_method = get_auto_ip_config_method; + device_class->act_stage3_ip_config = act_stage3_ip_config; device_class->deactivate = deactivate; device_class->unmanaged_on_quit = unmanaged_on_quit; diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index 82896c77..010cee08 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -32,7 +32,6 @@ #include "nm-setting-wireless-security.h" #include "nm-setting-8021x.h" #include "nm-setting-ip4-config.h" -#include "nm-ip4-config.h" #include "nm-setting-ip6-config.h" #include "libnm-platform/nm-platform.h" #include "nm-auth-utils.h" @@ -95,9 +94,9 @@ typedef struct { NMActRequestGetSecretsCallId *wifi_secrets_id; - NMSupplicantManager * sup_mgr; + NMSupplicantManager *sup_mgr; NMSupplMgrCreateIfaceHandle *sup_create_handle; - NMSupplicantInterface * sup_iface; + NMSupplicantInterface *sup_iface; gint64 scan_last_complete_msec; gint64 scan_periodic_next_msec; @@ -136,6 +135,8 @@ typedef struct { bool ssid_found : 1; bool hidden_probe_scan_warn : 1; + bool addressing_running_indicated : 1; + } NMDeviceWifiPrivate; struct _NMDeviceWifi { @@ -160,7 +161,7 @@ static void supplicant_iface_state_down(NMDeviceWifi *self); static void cleanup_association_attempt(NMDeviceWifi *self, gboolean disconnect); -static void supplicant_iface_state(NMDeviceWifi * self, +static void supplicant_iface_state(NMDeviceWifi *self, NMSupplicantInterfaceState new_state, NMSupplicantInterfaceState old_state, int disconnect_reason, @@ -173,27 +174,27 @@ static void supplicant_iface_state_cb(NMSupplicantInterface *iface, gpointer user_data); static void supplicant_iface_bss_changed_cb(NMSupplicantInterface *iface, - NMSupplicantBssInfo * bss_info, + NMSupplicantBssInfo *bss_info, gboolean is_present, - NMDeviceWifi * self); + NMDeviceWifi *self); static void supplicant_iface_wps_credentials_cb(NMSupplicantInterface *iface, - GVariant * credentials, - NMDeviceWifi * self); + GVariant *credentials, + NMDeviceWifi *self); static void supplicant_iface_notify_current_bss(NMSupplicantInterface *iface, - GParamSpec * pspec, - NMDeviceWifi * self); + GParamSpec *pspec, + NMDeviceWifi *self); static void supplicant_iface_notify_p2p_available(NMSupplicantInterface *iface, - GParamSpec * pspec, - NMDeviceWifi * self); + GParamSpec *pspec, + NMDeviceWifi *self); static void periodic_update(NMDeviceWifi *self); static void ap_add_remove(NMDeviceWifi *self, gboolean is_adding, - NMWifiAP * ap, + NMWifiAP *ap, gboolean recheck_available_connections); static void _hw_addr_set_scanning(NMDeviceWifi *self, gboolean do_reset); @@ -290,7 +291,7 @@ static GPtrArray * _scan_request_ssids_fetch(NMDeviceWifiPrivate *priv, gint64 now_msec) { ScanRequestSsidData *srs_data; - GPtrArray * ssids; + GPtrArray *ssids; guint len; _scan_request_ssids_remove_all(priv, now_msec, G_MAXUINT); @@ -331,7 +332,7 @@ _scan_request_ssids_track(NMDeviceWifiPrivate *priv, const GPtrArray *ssids) c_list_splice(&old_lst_head, &priv->scan_request_ssids_lst_head); for (i = 0; i < ssids->len; i++) { - GBytes * ssid = ssids->pdata[i]; + GBytes *ssid = ssids->pdata[i]; ScanRequestSsidData *d; G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(ScanRequestSsidData, ssid) == 0); @@ -364,7 +365,7 @@ nm_device_wifi_scanning_prohibited_track(NMDeviceWifi *self, gboolean temporarily_prohibited) { NMDeviceWifiPrivate *priv; - NMCListElem * elem; + NMCListElem *elem; g_return_if_fail(NM_IS_DEVICE_WIFI(self)); nm_assert(tag); @@ -394,10 +395,26 @@ nm_device_wifi_scanning_prohibited_track(NMDeviceWifi *self, /*****************************************************************************/ static void -_ap_dump(NMDeviceWifi * self, +_indicate_addressing_running_reset(NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + + if (!priv->addressing_running_indicated) + return; + + priv->addressing_running_indicated = FALSE; + nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(NM_DEVICE(self)), + nm_device_get_ifindex(NM_DEVICE(self)), + FALSE); +} + +/*****************************************************************************/ + +static void +_ap_dump(NMDeviceWifi *self, NMLogLevel log_level, const NMWifiAP *ap, - const char * prefix, + const char *prefix, gint64 now_msec) { char buf[1024]; @@ -530,8 +547,8 @@ _scan_notify_allowed(NMDeviceWifi *self, NMTernary do_kickoff) static void supplicant_iface_notify_scanning_cb(NMSupplicantInterface *iface, - GParamSpec * pspec, - NMDeviceWifi * self) + GParamSpec *pspec, + NMDeviceWifi *self) { _scan_notify_is_scanning(self); } @@ -549,13 +566,13 @@ unmanaged_on_quit(NMDevice *self) } static void -supplicant_interface_acquire_cb(NMSupplicantManager * supplicant_manager, +supplicant_interface_acquire_cb(NMSupplicantManager *supplicant_manager, NMSupplMgrCreateIfaceHandle *handle, - NMSupplicantInterface * iface, - GError * error, + NMSupplicantInterface *iface, + GError *error, gpointer user_data) { - NMDeviceWifi * self = user_data; + NMDeviceWifi *self = user_data; NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); if (nm_utils_error_is_cancelled(error)) @@ -694,7 +711,7 @@ static void set_current_ap(NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available_connections) { NMDeviceWifiPrivate *priv; - NMWifiAP * old_ap; + NMWifiAP *old_ap; g_return_if_fail(NM_IS_DEVICE_WIFI(self)); @@ -790,7 +807,7 @@ periodic_update_cb(gpointer user_data) static void ap_add_remove(NMDeviceWifi *self, gboolean is_adding, /* or else removing */ - NMWifiAP * ap, + NMWifiAP *ap, gboolean recheck_available_connections) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); @@ -831,7 +848,7 @@ static void remove_all_aps(NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMWifiAP * ap; + NMWifiAP *ap; if (c_list_is_empty(&priv->aps_lst_head)) return; @@ -847,7 +864,7 @@ remove_all_aps(NMDeviceWifi *self) static gboolean wake_on_wlan_restore(NMDeviceWifi *self) { - NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); _NMSettingWirelessWakeOnWLan w; w = priv->wowlan_restore; @@ -879,7 +896,7 @@ disconnect_cb_on_idle(gpointer user_data, GCancellable *cancellable) gs_unref_object NMDeviceWifi *self = NULL; NMDeviceDeactivateCallback callback; gpointer callback_user_data; - gs_free_error GError *cancelled_error = NULL; + gs_free_error GError *cancelled_error = NULL; nm_utils_user_data_unpack(user_data, &self, &callback, &callback_user_data); @@ -888,12 +905,12 @@ disconnect_cb_on_idle(gpointer user_data, GCancellable *cancellable) } static void -deactivate_async(NMDevice * device, - GCancellable * cancellable, +deactivate_async(NMDevice *device, + GCancellable *cancellable, NMDeviceDeactivateCallback callback, gpointer callback_user_data) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); gpointer user_data; @@ -917,7 +934,7 @@ deactivate_async(NMDevice * device, static void deactivate(NMDevice *device) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); int ifindex = nm_device_get_ifindex(device); @@ -932,8 +949,7 @@ deactivate(NMDevice *device) if (!wake_on_wlan_restore(self)) _LOGW(LOGD_DEVICE | LOGD_WIFI, "Cannot unconfigure WoWLAN."); - /* Clear any critical protocol notification in the Wi-Fi stack */ - nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), ifindex, FALSE); + _indicate_addressing_running_reset(self); /* Ensure we're in infrastructure mode after deactivation; some devices * (usually older ones) don't scan well in adhoc mode. @@ -962,14 +978,14 @@ deactivate_reset_hw_addr(NMDevice *device) static gboolean check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMSettingWireless * s_wireless; - const char * mac; - const char *const * mac_blacklist; + NMSettingWireless *s_wireless; + const char *mac; + const char *const *mac_blacklist; int i; - const char * mode; - const char * perm_hw_addr; + const char *mode; + const char *perm_hw_addr; if (!NM_DEVICE_CLASS(nm_device_wifi_parent_class) ->check_connection_compatible(device, connection, error)) @@ -1062,16 +1078,16 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, +check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMSettingWireless * s_wifi; - const char * mode; + NMSettingWireless *s_wifi; + const char *mode; s_wifi = nm_connection_get_setting_wireless(connection); g_return_val_if_fail(s_wifi, FALSE); @@ -1130,21 +1146,21 @@ check_connection_available(NMDevice * device, } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMSettingWireless * s_wifi; - gs_free char * ssid_utf8 = NULL; - NMWifiAP * ap; - GBytes * ssid = NULL; - GBytes * setting_ssid = NULL; + NMSettingWireless *s_wifi; + gs_free char *ssid_utf8 = NULL; + NMWifiAP *ap; + GBytes *ssid = NULL; + GBytes *setting_ssid = NULL; gboolean hidden = FALSE; - const char * mode; + const char *mode; s_wifi = nm_connection_get_setting_wireless(connection); @@ -1265,8 +1281,8 @@ complete_connection(NMDevice * device, static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); - NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); NMSupplicantInterfaceState supplicant_state; if (!priv->enabled) @@ -1292,12 +1308,12 @@ get_autoconnect_allowed(NMDevice *device) static gboolean can_auto_connect(NMDevice *device, NMSettingsConnection *sett_conn, char **specific_object) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMConnection * connection; - NMSettingWireless * s_wifi; - NMWifiAP * ap; - const char * method6, *mode; + NMConnection *connection; + NMSettingWireless *s_wifi; + NMWifiAP *ap; + const char *method6, *mode; gboolean auto4, auto6; nm_assert(!specific_object || !*specific_object); @@ -1345,7 +1361,7 @@ _nm_device_wifi_get_aps(NMDeviceWifi *self) static void _hw_addr_set_scanning(NMDeviceWifi *self, gboolean do_reset) { - NMDevice * device = (NMDevice *) self; + NMDevice *device = (NMDevice *) self; NMDeviceWifiPrivate *priv; guint32 now; gboolean randomize; @@ -1381,7 +1397,7 @@ _hw_addr_set_scanning(NMDeviceWifi *self, gboolean do_reset) if (now >= priv->hw_addr_scan_expire) { gs_free char *hw_addr_scan = NULL; - const char * generate_mac_address_mask; + const char *generate_mac_address_mask; /* the random MAC address for scanning expires after a while. * @@ -1428,7 +1444,7 @@ ssids_options_to_ptrarray(GVariant *value, GError **error) for (i = 0; i < num_ssids; i++) { gs_unref_variant GVariant *v = NULL; gsize len; - const guint8 * bytes; + const guint8 *bytes; v = g_variant_get_child_value(value, i); bytes = g_variant_get_fixed_array(v, &len, sizeof(guint8)); @@ -1455,14 +1471,14 @@ nmtst_ssids_options_to_ptrarray(GVariant *value, GError **error) } static void -dbus_request_scan_cb(NMDevice * device, +dbus_request_scan_cb(NMDevice *device, GDBusMethodInvocation *context, - NMAuthSubject * subject, - GError * error, + NMAuthSubject *subject, + GError *error, gpointer user_data) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); gs_unref_ptrarray GPtrArray *ssids = user_data; if (error) { @@ -1477,13 +1493,13 @@ dbus_request_scan_cb(NMDevice * device, } void -_nm_device_wifi_request_scan(NMDeviceWifi * self, - GVariant * options, +_nm_device_wifi_request_scan(NMDeviceWifi *self, + GVariant *options, GDBusMethodInvocation *invocation) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - gs_unref_ptrarray GPtrArray *ssids = NULL; + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); + gs_unref_ptrarray GPtrArray *ssids = NULL; if (options) { gs_unref_variant GVariant *val = g_variant_lookup_value(options, "ssids", NULL); @@ -1529,7 +1545,7 @@ _nm_device_wifi_request_scan(NMDeviceWifi * self, static gboolean hidden_filter_func(NMSettings *settings, NMSettingsConnection *set_con, gpointer user_data) { - NMConnection * connection = nm_settings_connection_get_connection(set_con); + NMConnection *connection = nm_settings_connection_get_connection(set_con); NMSettingWireless *s_wifi; if (!nm_connection_is_type(connection, NM_SETTING_WIRELESS_SETTING_NAME)) @@ -1545,12 +1561,12 @@ hidden_filter_func(NMSettings *settings, NMSettingsConnection *set_con, gpointer static GPtrArray * _scan_request_ssids_build_hidden(NMDeviceWifi *self, gint64 now_msec, - gboolean * out_has_hidden_profiles) + gboolean *out_has_hidden_profiles) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids(priv->sup_iface); + guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids(priv->sup_iface); gs_free NMSettingsConnection **connections = NULL; - gs_unref_ptrarray GPtrArray *ssids = NULL; + gs_unref_ptrarray GPtrArray *ssids = NULL; gs_unref_hashtable GHashTable *unique_ssids = NULL; guint connections_len; guint n_hidden; @@ -1608,7 +1624,7 @@ _scan_request_ssids_build_hidden(NMDeviceWifi *self, n_hidden = 0; for (i = 0; i < connections_len; i++) { NMSettingWireless *s_wifi; - GBytes * ssid; + GBytes *ssid; if (ssids->len >= max_scan_ssids) break; @@ -1637,7 +1653,7 @@ _scan_request_ssids_build_hidden(NMDeviceWifi *self, static gboolean _scan_request_delay_cb(gpointer user_data) { - NMDeviceWifi * self = user_data; + NMDeviceWifi *self = user_data; NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); nm_clear_g_source_inst(&priv->scan_request_delay_source); @@ -1650,10 +1666,10 @@ _scan_request_delay_cb(gpointer user_data) static void _scan_supplicant_request_scan_cb(NMSupplicantInterface *supp_iface, - GCancellable * cancellable, + GCancellable *cancellable, gpointer user_data) { - NMDeviceWifi * self; + NMDeviceWifi *self; NMDeviceWifiPrivate *priv; if (g_cancellable_is_cancelled(cancellable)) @@ -1680,7 +1696,7 @@ _scan_supplicant_request_scan_cb(NMSupplicantInterface *supp_iface, static gboolean _scan_kickoff_timeout_cb(gpointer user_data) { - NMDeviceWifi * self = user_data; + NMDeviceWifi *self = user_data; NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); priv->scan_kickoff_timeout_id = 0; @@ -1691,7 +1707,7 @@ _scan_kickoff_timeout_cb(gpointer user_data) static void _scan_kickoff(NMDeviceWifi *self) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); gs_unref_ptrarray GPtrArray *ssids = NULL; gboolean is_explict = FALSE; NMDeviceState device_state; @@ -1866,7 +1882,7 @@ _scan_kickoff(NMDeviceWifi *self) static gboolean ap_list_dump(gpointer user_data) { - NMDeviceWifi * self = NM_DEVICE_WIFI(user_data); + NMDeviceWifi *self = NM_DEVICE_WIFI(user_data); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); priv->ap_dump_id = 0; @@ -1904,7 +1920,7 @@ schedule_ap_list_dump(NMDeviceWifi *self) static void try_fill_ssid_for_hidden_ap(NMDeviceWifi *self, NMWifiAP *ap) { - const char * bssid; + const char *bssid; NMSettingsConnection *const *connections; guint i; @@ -1918,7 +1934,7 @@ try_fill_ssid_for_hidden_ap(NMDeviceWifi *self, NMWifiAP *ap) connections = nm_settings_get_connections(nm_device_get_settings((NMDevice *) self), NULL); for (i = 0; connections[i]; i++) { NMSettingsConnection *sett_conn = connections[i]; - NMSettingWireless * s_wifi; + NMSettingWireless *s_wifi; if (!nm_settings_connection_has_seen_bssid(sett_conn, bssid)) continue; @@ -1934,13 +1950,13 @@ try_fill_ssid_for_hidden_ap(NMDeviceWifi *self, NMWifiAP *ap) static void supplicant_iface_bss_changed_cb(NMSupplicantInterface *iface, - NMSupplicantBssInfo * bss_info, + NMSupplicantBssInfo *bss_info, gboolean is_present, - NMDeviceWifi * self) + NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMWifiAP * found_ap; - GBytes * ssid; + NMWifiAP *found_ap; + GBytes *ssid; found_ap = g_hash_table_lookup(priv->aps_idx_by_supplicant_path, bss_info->bss_path); @@ -2033,14 +2049,14 @@ cleanup_supplicant_failures(NMDeviceWifi *self) } static void -wifi_secrets_cb(NMActRequest * req, +wifi_secrets_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * connection, - GError * error, + NMSettingsConnection *connection, + GError *error, gpointer user_data) { - NMDevice * device = user_data; - NMDeviceWifi * self = user_data; + NMDevice *device = user_data; + NMDeviceWifi *self = user_data; NMDeviceWifiPrivate *priv; g_return_if_fail(NM_IS_DEVICE_WIFI(self)); @@ -2107,15 +2123,15 @@ wifi_secrets_cancel(NMDeviceWifi *self) static void supplicant_iface_wps_credentials_cb(NMSupplicantInterface *iface, - GVariant * credentials, - NMDeviceWifi * self) + GVariant *credentials, + NMDeviceWifi *self) { - NMActRequest * req; + NMActRequest *req; gs_unref_variant GVariant *val_key = NULL; gs_unref_variant GVariant *secrets = NULL; - gs_free_error GError *error = NULL; - const char * array; - gsize psk_len = 0; + gs_free_error GError *error = NULL; + const char *array; + gsize psk_len = 0; if (nm_device_get_state(NM_DEVICE(self)) != NM_DEVICE_STATE_NEED_AUTH) { _LOGI(LOGD_DEVICE | LOGD_WIFI, "WPS: The connection can't be updated with credentials"); @@ -2168,7 +2184,7 @@ supplicant_iface_wps_credentials_cb(NMSupplicantInterface *iface, static gboolean wps_timeout_cb(gpointer user_data) { - NMDeviceWifi * self = NM_DEVICE_WIFI(user_data); + NMDeviceWifi *self = NM_DEVICE_WIFI(user_data); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); priv->wps_timeout_id = 0; @@ -2183,12 +2199,12 @@ wps_timeout_cb(gpointer user_data) } static void -wifi_secrets_get_secrets(NMDeviceWifi * self, - const char * setting_name, +wifi_secrets_get_secrets(NMDeviceWifi *self, + const char *setting_name, NMSecretAgentGetSecretsFlags flags) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMActRequest * req; + NMActRequest *req; wifi_secrets_cancel(self); @@ -2209,8 +2225,8 @@ wifi_secrets_get_secrets(NMDeviceWifi * self, static gboolean link_timeout_cb(gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); _LOGW(LOGD_WIFI, "link timed out."); @@ -2234,14 +2250,14 @@ link_timeout_cb(gpointer user_data) } static gboolean -need_new_8021x_secrets(NMDeviceWifi * self, +need_new_8021x_secrets(NMDeviceWifi *self, NMSupplicantInterfaceState old_state, - const char ** setting_name) + const char **setting_name) { - NMSetting8021x * s_8021x; + NMSetting8021x *s_8021x; NMSettingWirelessSecurity *s_wsec; NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - NMConnection * connection; + NMConnection *connection; g_return_val_if_fail(setting_name, FALSE); @@ -2289,14 +2305,14 @@ need_new_8021x_secrets(NMDeviceWifi * self, } static gboolean -need_new_wpa_psk(NMDeviceWifi * self, +need_new_wpa_psk(NMDeviceWifi *self, NMSupplicantInterfaceState old_state, int disconnect_reason, - const char ** setting_name) + const char **setting_name) { NMSettingWirelessSecurity *s_wsec; - NMConnection * connection; - const char * key_mgmt = NULL; + NMConnection *connection; + const char *key_mgmt = NULL; g_return_val_if_fail(setting_name, FALSE); @@ -2331,14 +2347,14 @@ need_new_wpa_psk(NMDeviceWifi * self, } static gboolean -handle_8021x_or_psk_auth_fail(NMDeviceWifi * self, +handle_8021x_or_psk_auth_fail(NMDeviceWifi *self, NMSupplicantInterfaceState new_state, NMSupplicantInterfaceState old_state, int disconnect_reason) { - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMActRequest *req; - const char * setting_name = NULL; + const char *setting_name = NULL; gboolean handled = FALSE; g_return_val_if_fail(new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE); @@ -2370,8 +2386,8 @@ handle_8021x_or_psk_auth_fail(NMDeviceWifi * self, static gboolean reacquire_interface_cb(gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); priv->reacquire_iface_id = 0; @@ -2389,7 +2405,7 @@ static void supplicant_iface_state_down(NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); nm_device_queue_recheck_available(device, NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, @@ -2409,14 +2425,14 @@ supplicant_iface_state_down(NMDeviceWifi *self) } static void -supplicant_iface_state(NMDeviceWifi * self, +supplicant_iface_state(NMDeviceWifi *self, NMSupplicantInterfaceState new_state, NMSupplicantInterfaceState old_state, int disconnect_reason, gboolean is_real_signal) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceState devstate; gboolean scanning; gboolean scan_changed; @@ -2463,8 +2479,8 @@ supplicant_iface_state(NMDeviceWifi * self, */ if (devstate == NM_DEVICE_STATE_CONFIG) { NMSettingWireless *s_wifi; - GBytes * ssid; - gs_free char * ssid_str = NULL; + GBytes *ssid; + gs_free char *ssid_str = NULL; s_wifi = nm_device_get_applied_setting(NM_DEVICE(self), NM_TYPE_SETTING_WIRELESS); @@ -2478,7 +2494,7 @@ supplicant_iface_state(NMDeviceWifi * self, priv->mode == _NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot" : "Connected to wireless network", (ssid_str = _nm_utils_ssid_to_string_gbytes(ssid))); - nm_device_activate_schedule_stage3_ip_config_start(device); + nm_device_activate_schedule_stage3_ip_config(device, FALSE); } else if (devstate == NM_DEVICE_STATE_ACTIVATED) periodic_update(self); break; @@ -2540,7 +2556,7 @@ static void supplicant_iface_assoc_cb(NMSupplicantInterface *iface, GError *error, gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI(user_data); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); if (error && !nm_utils_error_is_cancelled_or_disposing(error) && nm_device_is_activating(device)) { @@ -2553,23 +2569,23 @@ supplicant_iface_assoc_cb(NMSupplicantInterface *iface, GError *error, gpointer static void supplicant_iface_notify_current_bss(NMSupplicantInterface *iface, - GParamSpec * pspec, - NMDeviceWifi * self) + GParamSpec *pspec, + NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMRefString * current_bss; - NMWifiAP * new_ap = NULL; - NMActRequest * req; + NMRefString *current_bss; + NMWifiAP *new_ap = NULL; + NMActRequest *req; current_bss = nm_supplicant_interface_get_current_bss(iface); if (current_bss) new_ap = g_hash_table_lookup(priv->aps_idx_by_supplicant_path, current_bss); if (new_ap != priv->current_ap) { - const char * new_bssid = NULL; - GBytes * new_ssid = NULL; - const char * old_bssid = NULL; - GBytes * old_ssid = NULL; + const char *new_bssid = NULL; + GBytes *new_ssid = NULL; + const char *old_bssid = NULL; + GBytes *old_ssid = NULL; gs_free char *new_ssid_s = NULL; gs_free char *old_ssid_s = NULL; @@ -2666,8 +2682,8 @@ recheck_p2p_availability(NMDeviceWifi *self) static void supplicant_iface_notify_p2p_available(NMSupplicantInterface *iface, - GParamSpec * pspec, - NMDeviceWifi * self) + GParamSpec *pspec, + NMDeviceWifi *self) { if (nm_supplicant_interface_get_state(iface) > NM_SUPPLICANT_INTERFACE_STATE_STARTING) recheck_p2p_availability(self); @@ -2676,14 +2692,14 @@ supplicant_iface_notify_p2p_available(NMSupplicantInterface *iface, static gboolean handle_auth_or_fail(NMDeviceWifi *self, NMActRequest *req, gboolean new_secrets) { - NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - const char * setting_name; - NMConnection * applied_connection; - NMSettingWirelessSecurity * s_wsec; - const char * bssid = NULL; + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + const char *setting_name; + NMConnection *applied_connection; + NMSettingWirelessSecurity *s_wsec; + const char *bssid = NULL; NM80211ApFlags ap_flags; NMSettingWirelessSecurityWpsMethod wps_method; - const char * type; + const char *type; NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; @@ -2761,11 +2777,11 @@ handle_auth_or_fail(NMDeviceWifi *self, NMActRequest *req, gboolean new_secrets) static gboolean supplicant_connection_timeout_cb(gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceWifi * self = NM_DEVICE_WIFI(user_data); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceWifi *self = NM_DEVICE_WIFI(user_data); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMActRequest * req; - NMConnection * connection; + NMActRequest *req; + NMConnection *connection; cleanup_association_attempt(self, TRUE); @@ -2841,12 +2857,12 @@ static NMSupplicantConfig * build_supplicant_config(NMDeviceWifi *self, NMConnection *connection, guint32 fixed_freq, - GError ** error) + GError **error) { - NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMSupplicantConfig * config = NULL; - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity * s_wireless_sec; + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMSupplicantConfig *config = NULL; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; NMSettingWirelessSecurityPmf pmf; NMSettingWirelessSecurityFils fils; NMTernary ap_isolation; @@ -2889,7 +2905,7 @@ build_supplicant_config(NMDeviceWifi *self, s_wireless_sec = nm_connection_get_setting_wireless_security(connection); if (s_wireless_sec) { NMSetting8021x *s_8021x; - const char * con_uuid = nm_connection_get_uuid(connection); + const char *con_uuid = nm_connection_get_uuid(connection); guint32 mtu = nm_platform_link_get_mtu(nm_device_get_platform(NM_DEVICE(self)), nm_device_get_ifindex(NM_DEVICE(self))); @@ -2950,10 +2966,10 @@ error: static gboolean wake_on_wlan_enable(NMDeviceWifi *self) { - NMDeviceWifiPrivate * priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); NMSettingWirelessWakeOnWLan wowl; _NMSettingWirelessWakeOnWLan wowl2; - NMSettingWireless * s_wireless; + NMSettingWireless *s_wireless; s_wireless = nm_device_get_applied_setting(NM_DEVICE(self), NM_TYPE_SETTING_WIRELESS); if (s_wireless) { @@ -3004,15 +3020,15 @@ found: static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMWifiAP * ap = NULL; + NMDeviceWifi *self = NM_DEVICE_WIFI(device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMWifiAP *ap = NULL; gs_unref_object NMWifiAP *ap_fake = NULL; - NMActRequest * req; - NMConnection * connection; - NMSettingWireless * s_wireless; - const char * mode; - const char * ap_path; + NMActRequest *req; + NMConnection *connection; + NMSettingWireless *s_wireless; + const char *mode; + const char *ap_path; req = nm_device_get_act_request(NM_DEVICE(self)); g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); @@ -3087,8 +3103,8 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static void ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP *ap) { - NMDevice * device = NM_DEVICE(self); - const char * band = nm_setting_wireless_get_band(s_wifi); + NMDevice *device = NM_DEVICE(self); + const char *band = nm_setting_wireless_get_band(s_wifi); const guint32 a_freqs[] = {5180, 5200, 5220, 5745, 5765, 5785, 5805, 0}; const guint32 bg_freqs[] = {2412, 2437, 2462, 2472, 0}; guint32 freq = 0; @@ -3117,8 +3133,8 @@ ensure_hotspot_frequency(NMDeviceWifi *self, NMSettingWireless *s_wifi, NMWifiAP static void set_powersave(NMDevice *device) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); - NMSettingWireless * s_wireless; + NMDeviceWifi *self = NM_DEVICE_WIFI(device); + NMSettingWireless *s_wireless; NMSettingWirelessPowersave val; s_wireless = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS); @@ -3148,20 +3164,20 @@ set_powersave(NMDevice *device) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); gs_unref_object NMSupplicantConfig *config = NULL; _NM80211Mode ap_mode; - NMActRequest * req; - NMWifiAP * ap; - NMConnection * connection; - const char * setting_name; - NMSettingWireless * s_wireless; - GError * error = NULL; + NMActRequest *req; + NMWifiAP *ap; + NMConnection *connection; + const char *setting_name; + NMSettingWireless *s_wireless; + GError *error = NULL; guint timeout; - NMActRequest * request; - NMActiveConnection * master_ac; - NMDevice * master; + NMActRequest *request; + NMActiveConnection *master_ac; + NMDevice *master; nm_clear_g_source(&priv->sup_timeout_id); nm_clear_g_source(&priv->link_timeout_id); @@ -3263,20 +3279,24 @@ out_fail: return NM_ACT_STAGE_RETURN_FAILURE; } -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) +static void +act_stage3_ip_config(NMDevice *device, int addr_family) { - gboolean indicate_addressing_running; - NMConnection *connection; - const char * method; + NMDeviceWifi *self = NM_DEVICE_WIFI(device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); + const char *method; + gboolean indicate_addressing_running; + + if (priv->addressing_running_indicated) + return; - connection = nm_device_get_applied_connection(device); + /* we always set the flag, even if we don't indicate it below. The reason + * is that we always want to *clear* the flag after we are done (as we don't + * know whether it isn't already set on the interface). */ + priv->addressing_running_indicated = TRUE; - method = nm_utils_get_ip_config_method(connection, addr_family); - if (addr_family == AF_INET) + method = nm_utils_get_ip_config_method(nm_device_get_applied_connection(device), addr_family); + if (NM_IS_IPv4(addr_family)) indicate_addressing_running = NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO); else { indicate_addressing_running = NM_IN_STRSET(method, @@ -3284,13 +3304,11 @@ act_stage3_ip_config_start(NMDevice * device, NM_SETTING_IP6_CONFIG_METHOD_DHCP); } - if (indicate_addressing_running) + if (indicate_addressing_running) { nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), nm_device_get_ip_ifindex(device), TRUE); - - return NM_DEVICE_CLASS(nm_device_wifi_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + } } static guint32 @@ -3301,90 +3319,18 @@ get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *ou out_source); } -static gboolean -is_static_wep(NMConnection *connection) -{ - NMSettingWirelessSecurity *s_wsec; - const char * str; - - g_return_val_if_fail(connection != NULL, FALSE); - - s_wsec = nm_connection_get_setting_wireless_security(connection); - if (!s_wsec) - return FALSE; - - str = nm_setting_wireless_security_get_key_mgmt(s_wsec); - if (g_strcmp0(str, "none") != 0) - return FALSE; - - str = nm_setting_wireless_security_get_auth_alg(s_wsec); - if (g_strcmp0(str, "leap") == 0) - return FALSE; - - return TRUE; -} - -static NMActStageReturn -act_stage4_ip_config_timeout(NMDevice * device, - int addr_family, - NMDeviceStateReason *out_failure_reason) -{ - NMDeviceWifi * self = NM_DEVICE_WIFI(device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - NMConnection * connection; - NMSettingIPConfig * s_ip; - gboolean may_fail; - - connection = nm_device_get_applied_connection(device); - s_ip = nm_connection_get_setting_ip_config(connection, addr_family); - may_fail = nm_setting_ip_config_get_may_fail(s_ip); - - if (priv->mode == _NM_802_11_MODE_AP) - goto call_parent; - - if (may_fail || !is_static_wep(connection)) { - /* Not static WEP or failure allowed; let superclass handle it */ - goto call_parent; - } - - /* If IP configuration times out and it's a static WEP connection, that - * usually means the WEP key is wrong. WEP's Open System auth mode has - * no provision for figuring out if the WEP key is wrong, so you just have - * to wait for DHCP to fail to figure it out. For all other Wi-Fi security - * types (open, WPA, 802.1x, etc) if the secrets/certs were wrong the - * connection would have failed before IP configuration. - * - * Activation failed, we must have bad encryption key */ - _LOGW(LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) could not get IP configuration for connection '%s'.", - nm_connection_get_id(connection)); - - if (!handle_auth_or_fail(self, NULL, TRUE)) { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_NO_SECRETS); - return NM_ACT_STAGE_RETURN_FAILURE; - } - - _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) asking for new secrets"); - return NM_ACT_STAGE_RETURN_POSTPONE; - -call_parent: - return NM_DEVICE_CLASS(nm_device_wifi_parent_class) - ->act_stage4_ip_config_timeout(device, addr_family, out_failure_reason); -} - static void activation_success_handler(NMDevice *device) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); int ifindex = nm_device_get_ifindex(device); - NMActRequest * req; + NMActRequest *req; req = nm_device_get_act_request(device); g_assert(req); - /* Clear any critical protocol notification in the wifi stack */ - nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), ifindex, FALSE); + _indicate_addressing_running_reset(self); /* There should always be a current AP, either a fake one because we haven't * seen a scan result for the activated AP yet, or a real one from the @@ -3439,12 +3385,12 @@ activation_success_handler(NMDevice *device) } static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); gboolean clear_aps = FALSE; @@ -3484,19 +3430,13 @@ device_state_changed(NMDevice * device, nm_supplicant_interface_disconnect(priv->sup_iface); break; case NM_DEVICE_STATE_IP_CHECK: - /* Clear any critical protocol notification in the wifi stack */ - nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), - nm_device_get_ifindex(device), - FALSE); + _indicate_addressing_running_reset(self); break; case NM_DEVICE_STATE_ACTIVATED: activation_success_handler(device); break; case NM_DEVICE_STATE_FAILED: - /* Clear any critical protocol notification in the wifi stack */ - nm_platform_wifi_indicate_addressing_running(nm_device_get_platform(device), - nm_device_get_ifindex(device), - FALSE); + _indicate_addressing_running_reset(self); break; case NM_DEVICE_STATE_DISCONNECTED: break; @@ -3519,7 +3459,7 @@ get_enabled(NMDevice *device) static void set_enabled(NMDevice *device, gboolean enabled) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); NMDeviceState state; @@ -3573,19 +3513,19 @@ set_enabled(NMDevice *device, gboolean enabled) static gboolean get_guessed_metered(NMDevice *device) { - NMDeviceWifi * self = NM_DEVICE_WIFI(device); + NMDeviceWifi *self = NM_DEVICE_WIFI(device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); return priv->current_ap && nm_wifi_ap_get_metered(priv->current_ap); } static gboolean -can_reapply_change(NMDevice * device, +can_reapply_change(NMDevice *device, const char *setting_name, - NMSetting * s_old, - NMSetting * s_new, + NMSetting *s_old, + NMSetting *s_new, GHashTable *diffs, - GError ** error) + GError **error) { NMDeviceClass *device_class; @@ -3623,9 +3563,9 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceWifi * self = NM_DEVICE_WIFI(object); + NMDeviceWifi *self = NM_DEVICE_WIFI(object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); - const char ** list; + const char **list; switch (prop_id) { case PROP_MODE: @@ -3664,7 +3604,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDeviceWifi * device = NM_DEVICE_WIFI(object); + NMDeviceWifi *device = NM_DEVICE_WIFI(object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(device); switch (prop_id) { @@ -3699,7 +3639,7 @@ nm_device_wifi_init(NMDeviceWifi *self) static void constructed(GObject *object) { - NMDeviceWifi * self = NM_DEVICE_WIFI(object); + NMDeviceWifi *self = NM_DEVICE_WIFI(object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); G_OBJECT_CLASS(nm_device_wifi_parent_class)->constructed(object); @@ -3733,7 +3673,7 @@ nm_device_wifi_new(const char *iface, _NMDeviceWifiCapabilities capabilities) static void dispose(GObject *object) { - NMDeviceWifi * self = NM_DEVICE_WIFI(object); + NMDeviceWifi *self = NM_DEVICE_WIFI(object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); nm_assert(c_list_is_empty(&priv->scanning_prohibited_lst_head)); @@ -3762,7 +3702,7 @@ dispose(GObject *object) static void finalize(GObject *object) { - NMDeviceWifi * self = NM_DEVICE_WIFI(object); + NMDeviceWifi *self = NM_DEVICE_WIFI(object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE(self); nm_assert(c_list_is_empty(&priv->aps_lst_head)); @@ -3776,9 +3716,9 @@ finalize(GObject *object) static void nm_device_wifi_class_init(NMDeviceWifiClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->constructed = constructed; object_class->get_property = get_property; @@ -3803,17 +3743,16 @@ nm_device_wifi_class_init(NMDeviceWifiClass *klass) device_class->get_guessed_metered = get_guessed_metered; device_class->set_enabled = set_enabled; - device_class->act_stage1_prepare = act_stage1_prepare; - device_class->act_stage2_config = act_stage2_config; - device_class->get_configured_mtu = get_configured_mtu; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->act_stage4_ip_config_timeout = act_stage4_ip_config_timeout; - device_class->deactivate_async = deactivate_async; - device_class->deactivate = deactivate; - device_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr; - device_class->unmanaged_on_quit = unmanaged_on_quit; - device_class->can_reapply_change = can_reapply_change; - device_class->reapply_connection = reapply_connection; + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage2_config = act_stage2_config; + device_class->get_configured_mtu = get_configured_mtu; + device_class->act_stage3_ip_config = act_stage3_ip_config; + device_class->deactivate_async = deactivate_async; + device_class->deactivate = deactivate; + device_class->deactivate_reset_hw_addr = deactivate_reset_hw_addr; + device_class->unmanaged_on_quit = unmanaged_on_quit; + device_class->can_reapply_change = can_reapply_change; + device_class->reapply_connection = reapply_connection; device_class->state_changed = device_state_changed; diff --git a/src/core/devices/wifi/nm-device-wifi.h b/src/core/devices/wifi/nm-device-wifi.h index c7ff1a14..3a85192e 100644 --- a/src/core/devices/wifi/nm-device-wifi.h +++ b/src/core/devices/wifi/nm-device-wifi.h @@ -37,8 +37,8 @@ NMDevice *nm_device_wifi_new(const char *iface, _NMDeviceWifiCapabilities capabi const CList *_nm_device_wifi_get_aps(NMDeviceWifi *self); -void _nm_device_wifi_request_scan(NMDeviceWifi * self, - GVariant * options, +void _nm_device_wifi_request_scan(NMDeviceWifi *self, + GVariant *options, GDBusMethodInvocation *invocation); GPtrArray *nmtst_ssids_options_to_ptrarray(GVariant *value, GError **error); diff --git a/src/core/devices/wifi/nm-iwd-manager.c b/src/core/devices/wifi/nm-iwd-manager.c index 56386c57..5563ebf8 100644 --- a/src/core/devices/wifi/nm-iwd-manager.c +++ b/src/core/devices/wifi/nm-iwd-manager.c @@ -15,6 +15,7 @@ #include "libnm-core-intern/nm-core-internal.h" #include "nm-manager.h" #include "nm-device-iwd.h" +#include "nm-device-iwd-p2p.h" #include "nm-wifi-utils.h" #include "libnm-glib-aux/nm-uuid.h" #include "libnm-glib-aux/nm-random-utils.h" @@ -25,30 +26,42 @@ /*****************************************************************************/ +enum { + P2P_DEVICE_ADDED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + typedef struct { - const char * name; + const char *name; NMIwdNetworkSecurity security; char buf[0]; } KnownNetworkId; typedef struct { - GDBusProxy * known_network; + GDBusProxy *known_network; NMSettingsConnection *mirror_connection; const KnownNetworkId *id; } KnownNetworkData; typedef struct { - NMManager * manager; - NMSettings * settings; - GCancellable * cancellable; + NMManager *manager; + NMSettings *settings; + GCancellable *cancellable; gboolean running; GDBusObjectManager *object_manager; guint agent_id; - char * agent_path; - GHashTable * known_networks; - NMDeviceIwd * last_agent_call_device; - char * last_state_dir; - char * warned_state_dir; + char *agent_path; + GHashTable *known_networks; + NMDeviceIwd *last_agent_call_device; + char *last_state_dir; + char *warned_state_dir; + bool netconfig_enabled; + GHashTable *p2p_devices; + NMIwdWfdInfo wfd_info; + guint wfd_use_count; } NMIwdManagerPrivate; struct _NMIwdManager { @@ -98,7 +111,7 @@ G_DEFINE_TYPE(NMIwdManager, nm_iwd_manager, G_TYPE_OBJECT) /*****************************************************************************/ static void mirror_connection_take_and_delete(NMSettingsConnection *sett_conn, - KnownNetworkData * data); + KnownNetworkData *data); /*****************************************************************************/ @@ -146,10 +159,10 @@ get_property_bool(GDBusProxy *proxy, const char *property, gboolean default_val) static NMDeviceIwd * get_device_from_network(NMIwdManager *self, GDBusProxy *network) { - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - const char * ifname; - const char * device_path; - NMDevice * device; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char *ifname; + const char *device_path; + NMDevice *device; gs_unref_object GDBusInterface *device_obj = NULL; /* Try not to rely on the path of the Device being a prefix of the @@ -182,21 +195,21 @@ get_device_from_network(NMIwdManager *self, GDBusProxy *network) } static void -agent_dbus_method_cb(GDBusConnection * connection, - const char * sender, - const char * object_path, - const char * interface_name, - const char * method_name, - GVariant * parameters, +agent_dbus_method_cb(GDBusConnection *connection, + const char *sender, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { - NMIwdManager * self = user_data; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - const char * network_path; - NMDeviceIwd * device; - gs_free char * name_owner = NULL; - gs_unref_object GDBusInterface *network = NULL; + NMIwdManager *self = user_data; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char *network_path; + NMDeviceIwd *device; + gs_free char *name_owner = NULL; + gs_unref_object GDBusInterface *network = NULL; /* Be paranoid and check the sender address */ name_owner = g_dbus_object_manager_client_get_name_owner( @@ -315,7 +328,7 @@ static void register_agent(NMIwdManager *self) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - GDBusInterface * agent_manager; + GDBusInterface *agent_manager; agent_manager = g_dbus_object_manager_get_interface(priv->object_manager, "/net/connman/iwd", /* IWD 1.0+ */ @@ -388,9 +401,9 @@ static void set_device_dbus_object(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *object) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - const char * ifname; + const char *ifname; int ifindex; - NMDevice * device; + NMDevice *device; int errsv; ifname = get_property_string_or_null(proxy, "Name"); @@ -420,10 +433,70 @@ set_device_dbus_object(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *objec } static void +add_p2p_device(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *object) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char *path = g_dbus_object_get_object_path(object); + NMDeviceIwdP2P *p2p; + gs_unref_object GDBusInterface *wiphy = NULL; + const char *phy_name; + + if (g_hash_table_contains(priv->p2p_devices, path)) + return; + + wiphy = g_dbus_object_get_interface(object, NM_IWD_WIPHY_INTERFACE); + if (!wiphy) + return; + + phy_name = get_property_string_or_null(G_DBUS_PROXY(wiphy), "Name"); + if (!phy_name) { + _LOGE("Name not cached for phy at %s", path); + return; + } + + p2p = nm_device_iwd_p2p_new(object); + if (!p2p) { + _LOGE("Can't create NMDeviceIwdP2P for phy at %s", path); + return; + } + + g_hash_table_insert(priv->p2p_devices, g_strdup(path), p2p); + g_signal_emit(self, signals[P2P_DEVICE_ADDED], 0, p2p, phy_name); + + /* There should be no peer objects before the device object appeared so don't + * try to look for them and notify the new device. */ +} + +static void +remove_p2p_device(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *object) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char *path = g_dbus_object_get_object_path(object); + NMDeviceIwdP2P *p2p = g_hash_table_lookup(priv->p2p_devices, path); + + if (!p2p) + return; + + g_hash_table_remove(priv->p2p_devices, path); +} + +static NMDeviceIwdP2P * +get_p2p_device_from_peer(NMIwdManager *self, GDBusProxy *proxy) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char *device_path = get_property_string_or_null(proxy, "Device"); + + if (!device_path) + return NULL; + + return g_hash_table_lookup(priv->p2p_devices, device_path); +} + +static void known_network_update_cb(GObject *source, GAsyncResult *res, gpointer user_data) { gs_unref_variant GVariant *variant = NULL; - gs_free_error GError *error = NULL; + gs_free_error GError *error = NULL; variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant) { @@ -436,13 +509,13 @@ known_network_update_cb(GObject *source, GAsyncResult *res, gpointer user_data) } static gboolean -iwd_config_write(GKeyFile * config, - const char * filepath, +iwd_config_write(GKeyFile *config, + const char *filepath, const struct timespec *mtime, - GError ** error) + GError **error) { gsize length; - gs_free char * data = g_key_file_to_data(config, &length, NULL); + gs_free char *data = g_key_file_to_data(config, &length, NULL); struct timespec times[2] = {{.tv_nsec = UTIME_OMIT}, *mtime}; /* Atomically write or replace the file with the right permission bits @@ -458,7 +531,7 @@ static const char * get_config_path(NMIwdManager *self) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - const char * path; + const char *path; path = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA); if (path && path[0] == '\0') { @@ -489,26 +562,26 @@ get_config_path(NMIwdManager *self) } static void -sett_conn_changed(NMSettingsConnection * sett_conn, +sett_conn_changed(NMSettingsConnection *sett_conn, guint update_reason, const KnownNetworkData *data) { - NMSettingsConnectionIntFlags flags; - NMConnection * conn = nm_settings_connection_get_connection(sett_conn); - NMSettingConnection * s_conn = nm_connection_get_setting_connection(conn); - NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(conn); + NMSettingsConnectionIntFlags flags; + NMConnection *conn = nm_settings_connection_get_connection(sett_conn); + NMSettingConnection *s_conn = nm_connection_get_setting_connection(conn); + NMSettingWireless *s_wifi = nm_connection_get_setting_wireless(conn); nm_auto_unref_keyfile GKeyFile *iwd_config = NULL; - const char * iwd_dir; - gs_free char * filename = NULL; - gs_free char * full_path = NULL; - gs_free_error GError *error = NULL; - NMIwdNetworkSecurity security; - GBytes * ssid; - const guint8 * ssid_data; - gsize ssid_len; - gboolean removed; - GStatBuf statbuf; - gboolean have_mtime; + const char *iwd_dir; + gs_free char *filename = NULL; + gs_free char *full_path = NULL; + gs_free_error GError *error = NULL; + NMIwdNetworkSecurity security; + GBytes *ssid; + const guint8 *ssid_data; + gsize ssid_len; + gboolean removed; + GStatBuf statbuf; + gboolean have_mtime; nm_assert(sett_conn == data->mirror_connection); @@ -660,24 +733,24 @@ sett_conn_changed(NMSettingsConnection * sett_conn, * from the user. */ static NMSettingsConnection * -mirror_connection(NMIwdManager * self, +mirror_connection(NMIwdManager *self, const KnownNetworkId *id, gboolean create_new, - GDBusProxy * known_network) + GDBusProxy *known_network) { - NMIwdManagerPrivate * priv = NM_IWD_MANAGER_GET_PRIVATE(self); - NMSettingsConnection *const *iter; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + NMSettingsConnection *const *iter; gs_unref_object NMConnection *connection = NULL; - NMSettingsConnection * settings_connection = NULL; + NMSettingsConnection *settings_connection = NULL; char uuid[37]; - NMSetting * setting; - gs_free_error GError *error = NULL; - gs_unref_bytes GBytes *new_ssid = NULL; - gsize ssid_len = strlen(id->name); - gboolean autoconnectable = TRUE; - gboolean hidden = FALSE; - gboolean exact_match = TRUE; - const char * key_mgmt = NULL; + NMSetting *setting; + gs_free_error GError *error = NULL; + gs_unref_bytes GBytes *new_ssid = NULL; + gsize ssid_len = strlen(id->name); + gboolean autoconnectable = TRUE; + gboolean hidden = FALSE; + gboolean exact_match = TRUE; + const char *key_mgmt = NULL; if (known_network) { autoconnectable = get_property_bool(known_network, "AutoConnect", TRUE); @@ -686,10 +759,10 @@ mirror_connection(NMIwdManager * self, for (iter = nm_settings_get_connections(priv->settings, NULL); *iter; iter++) { NMSettingsConnection *sett_conn = *iter; - NMConnection * conn = nm_settings_connection_get_connection(sett_conn); + NMConnection *conn = nm_settings_connection_get_connection(sett_conn); NMIwdNetworkSecurity security; - NMSettingWireless * s_wifi; - const guint8 * ssid_bytes; + NMSettingWireless *s_wifi; + const guint8 *ssid_bytes; gsize ssid_len2; if (!nm_wifi_connection_get_iwd_ssid_and_security(conn, NULL, &security)) @@ -770,7 +843,7 @@ mirror_connection(NMIwdManager * self, if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) { NMConnection *tmp_conn = nm_settings_connection_get_connection(settings_connection); NMSettingConnection *s_conn = nm_connection_get_setting_connection(tmp_conn); - NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(tmp_conn); + NMSettingWireless *s_wifi = nm_connection_get_setting_wireless(tmp_conn); g_object_set(G_OBJECT(s_conn), NM_SETTING_CONNECTION_AUTOCONNECT, @@ -912,14 +985,14 @@ mirror_connection_take_and_delete(NMSettingsConnection *sett_conn, KnownNetworkD static void interface_added(GDBusObjectManager *object_manager, - GDBusObject * object, - GDBusInterface * interface, + GDBusObject *object, + GDBusInterface *interface, gpointer user_data) { - NMIwdManager * self = user_data; + NMIwdManager *self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - GDBusProxy * proxy; - const char * iface_name; + GDBusProxy *proxy; + const char *iface_name; if (!priv->running) return; @@ -935,11 +1008,11 @@ interface_added(GDBusObjectManager *object_manager, } if (nm_streq(iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) { - KnownNetworkId * id; - KnownNetworkId * orig_id; - KnownNetworkData * data; + KnownNetworkId *id; + KnownNetworkId *orig_id; + KnownNetworkData *data; NMIwdNetworkSecurity security; - const char * type_str, *name; + const char *type_str, *name; NMSettingsConnection *sett_conn = NULL; type_str = get_property_string_or_null(proxy, "Type"); @@ -998,18 +1071,34 @@ interface_added(GDBusObjectManager *object_manager, return; } + + if (nm_streq(iface_name, NM_IWD_P2P_INTERFACE)) { + add_p2p_device(self, proxy, object); + return; + } + + if (nm_streq(iface_name, NM_IWD_P2P_PEER_INTERFACE)) { + NMDeviceIwdP2P *p2p = get_p2p_device_from_peer(self, proxy); + + /* This is more conveniently done with a direct call than a signal because + * this way we only notify the interested NMDeviceIwdP2P. */ + if (p2p) + nm_device_iwd_p2p_peer_add_remove(p2p, object, TRUE); + + return; + } } static void interface_removed(GDBusObjectManager *object_manager, - GDBusObject * object, - GDBusInterface * interface, + GDBusObject *object, + GDBusInterface *interface, gpointer user_data) { - NMIwdManager * self = user_data; + NMIwdManager *self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - GDBusProxy * proxy; - const char * iface_name; + GDBusProxy *proxy; + const char *iface_name; g_return_if_fail(G_IS_DBUS_PROXY(interface)); @@ -1023,7 +1112,7 @@ interface_removed(GDBusObjectManager *object_manager, if (nm_streq(iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) { KnownNetworkId id; - const char * type_str; + const char *type_str; type_str = get_property_string_or_null(proxy, "Type"); id.name = get_property_string_or_null(proxy, "Name"); @@ -1051,6 +1140,20 @@ interface_removed(GDBusObjectManager *object_manager, return; } + + if (nm_streq(iface_name, NM_IWD_P2P_INTERFACE)) { + remove_p2p_device(self, proxy, object); + return; + } + + if (nm_streq(iface_name, NM_IWD_P2P_PEER_INTERFACE)) { + NMDeviceIwdP2P *p2p = get_p2p_device_from_peer(self, proxy); + + if (p2p) + nm_device_iwd_p2p_peer_add_remove(p2p, object, FALSE); + + return; + } } static void @@ -1088,19 +1191,19 @@ object_removed(GDBusObjectManager *object_manager, GDBusObject *object, gpointer static void connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer user_data) { - NMIwdManager * self = user_data; - NMIwdManagerPrivate * priv = NM_IWD_MANAGER_GET_PRIVATE(self); - NMConnection * conn = nm_settings_connection_get_connection(sett_conn); - NMSettingWireless * s_wireless; - KnownNetworkData * data; + NMIwdManager *self = user_data; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + NMConnection *conn = nm_settings_connection_get_connection(sett_conn); + NMSettingWireless *s_wireless; + KnownNetworkData *data; KnownNetworkId id; char ssid_buf[33]; - const guint8 * ssid_bytes; + const guint8 *ssid_bytes; gsize ssid_len; NMSettingsConnection *new_mirror_conn; - const char * iwd_dir; - gs_free char * filename = NULL; - gs_free char * full_path = NULL; + const char *iwd_dir; + gs_free char *filename = NULL; + gs_free char *full_path = NULL; if (!nm_wifi_connection_get_iwd_ssid_and_security(conn, NULL, &id.security)) return; @@ -1170,13 +1273,13 @@ try_delete_file: static void connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer user_data) { - NMIwdManager * self = user_data; - NMConnection * conn = nm_settings_connection_get_connection(sett_conn); - NMSettingConnection *s_conn = nm_connection_get_setting_connection(conn); - const char * iwd_dir; - gs_free char * filename = NULL; - gs_free char * full_path = NULL; - gs_free_error GError *error = NULL; + NMIwdManager *self = user_data; + NMConnection *conn = nm_settings_connection_get_connection(sett_conn); + NMSettingConnection *s_conn = nm_connection_get_setting_connection(conn); + const char *iwd_dir; + gs_free char *filename = NULL; + gs_free char *full_path = NULL; + gs_free_error GError *error = NULL; nm_auto_unref_keyfile GKeyFile *iwd_config = NULL; NMSettingsConnectionIntFlags flags; @@ -1259,7 +1362,7 @@ release_object_manager(NMIwdManager *self) g_signal_handlers_disconnect_by_data(priv->object_manager, self); if (priv->agent_id) { - GDBusConnection * agent_connection; + GDBusConnection *agent_connection; GDBusObjectManagerClient *omc = G_DBUS_OBJECT_MANAGER_CLIENT(priv->object_manager); agent_connection = g_dbus_object_manager_client_get_connection(omc); @@ -1281,9 +1384,9 @@ static void prepare_object_manager(NMIwdManager *self); static void name_owner_changed(GObject *object, GParamSpec *pspec, gpointer user_data) { - NMIwdManager * self = user_data; + NMIwdManager *self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - GDBusObjectManager * object_manager = G_DBUS_OBJECT_MANAGER(object); + GDBusObjectManager *object_manager = G_DBUS_OBJECT_MANAGER(object); nm_assert(object_manager == priv->object_manager); @@ -1292,7 +1395,7 @@ name_owner_changed(GObject *object, GParamSpec *pspec, gpointer user_data) prepare_object_manager(self); } else { const CList *tmp_lst; - NMDevice * device; + NMDevice *device; if (!priv->running) return; @@ -1310,9 +1413,9 @@ name_owner_changed(GObject *object, GParamSpec *pspec, gpointer user_data) static void device_added(NMManager *manager, NMDevice *device, gpointer user_data) { - NMIwdManager * self = user_data; + NMIwdManager *self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - GList * objects, *iter; + GList *objects, *iter; if (!NM_IS_DEVICE_IWD(device)) return; @@ -1331,7 +1434,7 @@ device_added(NMManager *manager, NMDevice *device, gpointer user_data) objects = g_dbus_object_manager_get_objects(priv->object_manager); for (iter = objects; iter; iter = iter->next) { - GDBusObject * object = G_DBUS_OBJECT(iter->data); + GDBusObject *object = G_DBUS_OBJECT(iter->data); gs_unref_object GDBusInterface *interface = NULL; interface = g_dbus_object_get_interface(object, NM_IWD_NETWORK_INTERFACE); @@ -1343,9 +1446,9 @@ device_added(NMManager *manager, NMDevice *device, gpointer user_data) } for (iter = objects; iter; iter = iter->next) { - GDBusObject * object = G_DBUS_OBJECT(iter->data); + GDBusObject *object = G_DBUS_OBJECT(iter->data); gs_unref_object GDBusInterface *interface = NULL; - const char * obj_ifname; + const char *obj_ifname; interface = g_dbus_object_get_interface(object, NM_IWD_DEVICE_INTERFACE); obj_ifname = get_property_string_or_null((GDBusProxy *) interface, "Name"); @@ -1363,7 +1466,7 @@ device_added(NMManager *manager, NMDevice *device, gpointer user_data) static void device_removed(NMManager *manager, NMDevice *device, gpointer user_data) { - NMIwdManager * self = user_data; + NMIwdManager *self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); if (!NM_IS_DEVICE_IWD(device)) @@ -1431,13 +1534,13 @@ object_compare_interfaces(gconstpointer a, gconstpointer b) static void get_daemon_info_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMIwdManager * self = user_data; - NMIwdManagerPrivate *priv; + NMIwdManager *self = user_data; + NMIwdManagerPrivate *priv; gs_unref_variant GVariant *properties = NULL; - gs_free_error GError *error = NULL; - GVariantIter * properties_iter; - const char * key; - GVariant * value; + gs_free_error GError *error = NULL; + GVariantIter *properties_iter; + const char *key; + GVariant *value; properties = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!properties) { @@ -1469,6 +1572,15 @@ get_daemon_info_cb(GObject *source, GAsyncResult *res, gpointer user_data) nm_clear_g_free(&priv->last_state_dir); priv->last_state_dir = g_variant_dup_string(value, NULL); + } else if (nm_streq(key, "NetworkConfigurationEnabled")) { + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) { + _LOGE("Daemon.GetInfo property %s is typed '%s' instead of 'b'", + key, + g_variant_get_type_string(value)); + goto next; + } + + priv->netconfig_enabled = g_variant_get_boolean(value); } next: @@ -1481,11 +1593,11 @@ next: static void got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) { - NMIwdManager * self = user_data; + NMIwdManager *self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - GError * error = NULL; - GDBusObjectManager * object_manager; - GDBusConnection * connection; + GError *error = NULL; + GDBusObjectManager *object_manager; + GDBusConnection *connection; object_manager = g_dbus_object_manager_client_new_for_bus_finish(result, &error); if (object_manager == NULL) { @@ -1515,7 +1627,7 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) } if (_om_has_name_owner(object_manager)) { - GList * objects, *iter; + GList *objects, *iter; gs_unref_object GDBusInterface *daemon = NULL; priv->running = true; @@ -1543,6 +1655,8 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) if (priv->agent_id) register_agent(self); + priv->netconfig_enabled = false; /* Assume false until GetInfo() results come in */ + daemon = g_dbus_object_manager_get_interface(object_manager, "/net/connman/iwd", /* IWD 1.15+ */ NM_IWD_DAEMON_INTERFACE); @@ -1587,11 +1701,11 @@ nm_iwd_manager_is_known_network(NMIwdManager *self, const char *name, NMIwdNetwo NMSettingsConnection * nm_iwd_manager_get_ap_mirror_connection(NMIwdManager *self, NMWifiAP *ap) { - NMIwdManagerPrivate * priv = NM_IWD_MANAGER_GET_PRIVATE(self); - KnownNetworkData * data; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + KnownNetworkData *data; char name_buf[33]; KnownNetworkId kn_id = {name_buf, NM_IWD_NETWORK_SECURITY_OPEN}; - const guint8 * ssid_bytes; + const guint8 *ssid_bytes; gsize ssid_len; NM80211ApFlags flags = nm_wifi_ap_get_flags(ap); NM80211ApSecurityFlags sec_flags = nm_wifi_ap_get_wpa_flags(ap) | nm_wifi_ap_get_rsn_flags(ap); @@ -1629,7 +1743,7 @@ GDBusProxy * nm_iwd_manager_get_dbus_interface(NMIwdManager *self, const char *path, const char *name) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - GDBusInterface * interface; + GDBusInterface *interface; if (!priv->object_manager) return NULL; @@ -1639,6 +1753,121 @@ nm_iwd_manager_get_dbus_interface(NMIwdManager *self, const char *path, const ch return interface ? G_DBUS_PROXY(interface) : NULL; } +gboolean +nm_iwd_manager_get_netconfig_enabled(NMIwdManager *self) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + + return priv->netconfig_enabled; +} + +/* IWD's net.connman.iwd.p2p.ServiceManager.RegisterDisplayService() is global so + * two local Wi-Fi P2P devices can't be connected to (or even scanning for) WFD + * peers using different WFD IE contents, e.g. one as a sink and one as a source. + * If one device is connected to a peer without a WFD service, another can try + * to establish a WFD connection to a peer since this won't disturb the first + * connection. Similarly if one device is connected to a peer with WFD, another + * can make a connection to a non-WFD peer (if that exists...) because a non-WFD + * peer will simply ignore the WFD IEs, but it cannot connect to or search for a + * peer that's WFD capable without passing our own WFD IEs, i.e. if the new + * NMSettingsConnection has no WFD IEs and we're already in a WFD connection on + * another device, we can't activate that new connection. We expose methods + * for the NMDeviceIwdP2P's to register/unregister the service and one to check + * if there's already an incompatible connection active. + */ +gboolean +nm_iwd_manager_check_wfd_info_compatible(NMIwdManager *self, const NMIwdWfdInfo *wfd_info) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + + if (priv->wfd_use_count == 0) + return TRUE; + + return nm_wifi_utils_wfd_info_eq(&priv->wfd_info, wfd_info); +} + +gboolean +nm_iwd_manager_register_wfd(NMIwdManager *self, const NMIwdWfdInfo *wfd_info) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + gs_unref_object GDBusInterface *service_manager = NULL; + GVariantBuilder builder; + + nm_assert(nm_iwd_manager_check_wfd_info_compatible(self, wfd_info)); + + if (!priv->object_manager) + return FALSE; + + service_manager = g_dbus_object_manager_get_interface(priv->object_manager, + "/net/connman/iwd", + NM_IWD_P2P_SERVICE_MANAGER_INTERFACE); + if (!service_manager) { + _LOGE("IWD P2P service manager not found"); + return FALSE; + } + + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add(&builder, "{sv}", "Source", g_variant_new_boolean(wfd_info->source)); + g_variant_builder_add(&builder, "{sv}", "Sink", g_variant_new_boolean(wfd_info->sink)); + + if (wfd_info->source) + g_variant_builder_add(&builder, "{sv}", "Port", g_variant_new_uint16(wfd_info->port)); + + if (wfd_info->sink && wfd_info->has_audio) + g_variant_builder_add(&builder, "{sv}", "HasAudio", g_variant_new_boolean(TRUE)); + + if (wfd_info->has_uibc) + g_variant_builder_add(&builder, "{sv}", "HasUIBC", g_variant_new_boolean(TRUE)); + + if (wfd_info->has_cp) + g_variant_builder_add(&builder, + "{sv}", + "HasContentProtection", + g_variant_new_boolean(TRUE)); + + g_dbus_proxy_call(G_DBUS_PROXY(service_manager), + "RegisterDisplayService", + g_variant_new("(a{sv})", &builder), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); + + memcpy(&priv->wfd_info, wfd_info, sizeof(priv->wfd_info)); + priv->wfd_use_count++; + return TRUE; +} + +void +nm_iwd_manager_unregister_wfd(NMIwdManager *self) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + gs_unref_object GDBusInterface *service_manager = NULL; + + nm_assert(priv->wfd_use_count > 0); + + priv->wfd_use_count--; + + if (!priv->object_manager) + return; + + service_manager = g_dbus_object_manager_get_interface(priv->object_manager, + "/net/connman/iwd", + NM_IWD_P2P_SERVICE_MANAGER_INTERFACE); + if (!service_manager) + return; + + g_dbus_proxy_call(G_DBUS_PROXY(service_manager), + "UnregisterDisplayService", + g_variant_new("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); +} + /*****************************************************************************/ NM_DEFINE_SINGLETON_GETTER(NMIwdManager, nm_iwd_manager_get, NM_TYPE_IWD_MANAGER); @@ -1685,13 +1914,15 @@ nm_iwd_manager_init(NMIwdManager *self) g_free, (GDestroyNotify) known_network_data_free); + priv->p2p_devices = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_object_unref); + prepare_object_manager(self); } static void dispose(GObject *object) { - NMIwdManager * self = (NMIwdManager *) object; + NMIwdManager *self = (NMIwdManager *) object; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); release_object_manager(self); @@ -1718,6 +1949,8 @@ dispose(GObject *object) nm_clear_g_free(&priv->last_state_dir); nm_clear_g_free(&priv->warned_state_dir); + g_hash_table_unref(nm_steal_pointer(&priv->p2p_devices)); + G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object); } @@ -1727,4 +1960,16 @@ nm_iwd_manager_class_init(NMIwdManagerClass *klass) GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->dispose = dispose; + + signals[P2P_DEVICE_ADDED] = g_signal_new(NM_IWD_MANAGER_P2P_DEVICE_ADDED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + NM_TYPE_DEVICE, + G_TYPE_STRING); } diff --git a/src/core/devices/wifi/nm-iwd-manager.h b/src/core/devices/wifi/nm-iwd-manager.h index e794e661..02cd6bba 100644 --- a/src/core/devices/wifi/nm-iwd-manager.h +++ b/src/core/devices/wifi/nm-iwd-manager.h @@ -13,18 +13,22 @@ #define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM #define NM_IWD_SERVICE "net.connman.iwd" -#define NM_IWD_DAEMON_INTERFACE "net.connman.iwd.Daemon" -#define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager" -#define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter" -#define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device" -#define NM_IWD_NETWORK_INTERFACE "net.connman.iwd.Network" -#define NM_IWD_AGENT_INTERFACE "net.connman.iwd.Agent" -#define NM_IWD_WSC_INTERFACE "net.connman.iwd.WiFiSimpleConfiguration" -#define NM_IWD_KNOWN_NETWORK_INTERFACE "net.connman.iwd.KnownNetwork" -#define NM_IWD_SIGNAL_AGENT_INTERFACE "net.connman.iwd.SignalLevelAgent" -#define NM_IWD_AP_INTERFACE "net.connman.iwd.AccessPoint" -#define NM_IWD_ADHOC_INTERFACE "net.connman.iwd.AdHoc" -#define NM_IWD_STATION_INTERFACE "net.connman.iwd.Station" +#define NM_IWD_DAEMON_INTERFACE "net.connman.iwd.Daemon" +#define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager" +#define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter" +#define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device" +#define NM_IWD_NETWORK_INTERFACE "net.connman.iwd.Network" +#define NM_IWD_AGENT_INTERFACE "net.connman.iwd.Agent" +#define NM_IWD_WSC_INTERFACE "net.connman.iwd.SimpleConfiguration" +#define NM_IWD_KNOWN_NETWORK_INTERFACE "net.connman.iwd.KnownNetwork" +#define NM_IWD_SIGNAL_AGENT_INTERFACE "net.connman.iwd.SignalLevelAgent" +#define NM_IWD_AP_INTERFACE "net.connman.iwd.AccessPoint" +#define NM_IWD_ADHOC_INTERFACE "net.connman.iwd.AdHoc" +#define NM_IWD_STATION_INTERFACE "net.connman.iwd.Station" +#define NM_IWD_P2P_INTERFACE "net.connman.iwd.p2p.Device" +#define NM_IWD_P2P_PEER_INTERFACE "net.connman.iwd.p2p.Peer" +#define NM_IWD_P2P_SERVICE_MANAGER_INTERFACE "net.connman.iwd.p2p.ServiceManager" +#define NM_IWD_P2P_WFD_INTERFACE "net.connman.iwd.p2p.Display" #define NM_TYPE_IWD_MANAGER (nm_iwd_manager_get_type()) #define NM_IWD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IWD_MANAGER, NMIwdManager)) @@ -35,6 +39,8 @@ #define NM_IWD_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_IWD_MANAGER, NMIwdManagerClass)) +#define NM_IWD_MANAGER_P2P_DEVICE_ADDED "p2p-device-added" + typedef struct _NMIwdManager NMIwdManager; typedef struct _NMIwdManagerClass NMIwdManagerClass; @@ -42,8 +48,8 @@ GType nm_iwd_manager_get_type(void); NMIwdManager *nm_iwd_manager_get(void); -gboolean nm_iwd_manager_is_known_network(NMIwdManager * self, - const char * name, +gboolean nm_iwd_manager_is_known_network(NMIwdManager *self, + const char *name, NMIwdNetworkSecurity security); NMSettingsConnection *nm_iwd_manager_get_ap_mirror_connection(NMIwdManager *self, NMWifiAP *ap); @@ -51,4 +57,10 @@ NMSettingsConnection *nm_iwd_manager_get_ap_mirror_connection(NMIwdManager *self GDBusProxy * nm_iwd_manager_get_dbus_interface(NMIwdManager *self, const char *path, const char *name); +gboolean nm_iwd_manager_get_netconfig_enabled(NMIwdManager *self); + +gboolean nm_iwd_manager_check_wfd_info_compatible(NMIwdManager *self, const NMIwdWfdInfo *wfd_info); +gboolean nm_iwd_manager_register_wfd(NMIwdManager *self, const NMIwdWfdInfo *wfd_info); +void nm_iwd_manager_unregister_wfd(NMIwdManager *self); + #endif /* __NETWORKMANAGER_IWD_MANAGER_H__ */ diff --git a/src/core/devices/wifi/nm-wifi-ap.c b/src/core/devices/wifi/nm-wifi-ap.c index 72a60885..ac0b748a 100644 --- a/src/core/devices/wifi/nm-wifi-ap.c +++ b/src/core/devices/wifi/nm-wifi-ap.c @@ -41,8 +41,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMWifiAP, struct _NMWifiAPPrivate { /* Scanned or cached values */ - GBytes * ssid; - char * address; + GBytes *ssid; + char *address; _NM80211Mode mode; guint8 strength; guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ @@ -430,7 +430,7 @@ has_proto(NMSettingWirelessSecurity *sec, const char *proto) static void add_pair_ciphers(NMWifiAP *ap, NMSettingWirelessSecurity *sec) { - NMWifiAPPrivate * priv = NM_WIFI_AP_GET_PRIVATE(ap); + NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(ap); guint32 num = nm_setting_wireless_security_get_num_pairwise(sec); NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; guint32 i; @@ -458,7 +458,7 @@ add_pair_ciphers(NMWifiAP *ap, NMSettingWirelessSecurity *sec) static void add_group_ciphers(NMWifiAP *ap, NMSettingWirelessSecurity *sec) { - NMWifiAPPrivate * priv = NM_WIFI_AP_GET_PRIVATE(ap); + NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(ap); guint32 num = nm_setting_wireless_security_get_num_groups(sec); NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; guint32 i; @@ -491,10 +491,10 @@ const char * nm_wifi_ap_to_string(const NMWifiAP *self, char *str_buf, gulong buf_len, gint64 now_msec) { const NMWifiAPPrivate *priv; - const char * supplicant_id = "-"; - const char * export_path; + const char *supplicant_id = "-"; + const char *export_path; guint32 chan; - gs_free char * ssid_to_free = NULL; + gs_free char *ssid_to_free = NULL; char str_buf_ts[100]; g_return_val_if_fail(NM_IS_WIFI_AP(self), NULL); @@ -558,13 +558,13 @@ freq_to_band(guint32 freq) gboolean nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection) { - NMWifiAPPrivate * priv; - NMSettingWireless * s_wireless; + NMWifiAPPrivate *priv; + NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; - GBytes * ssid; - const char * mode; - const char * band; - const char * bssid; + GBytes *ssid; + const char *mode; + const char *band; + const char *bssid; guint32 channel; g_return_val_if_fail(NM_IS_WIFI_AP(self), FALSE); @@ -629,10 +629,10 @@ nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection) } gboolean -nm_wifi_ap_complete_connection(NMWifiAP * self, +nm_wifi_ap_complete_connection(NMWifiAP *self, NMConnection *connection, gboolean lock_bssid, - GError ** error) + GError **error) { NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(self); @@ -655,7 +655,7 @@ nm_wifi_ap_complete_connection(NMWifiAP * self, static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMWifiAP * self = NM_WIFI_AP(object); + NMWifiAP *self = NM_WIFI_AP(object); NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(self); switch (prop_id) { @@ -734,11 +734,11 @@ nm_wifi_ap_new_from_properties(const NMSupplicantBssInfo *bss_info) NMWifiAP * nm_wifi_ap_new_fake_from_connection(NMConnection *connection) { - NMWifiAP * ap; - NMWifiAPPrivate * priv; - NMSettingWireless * s_wireless; + NMWifiAP *ap; + NMWifiAPPrivate *priv; + NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; - const char * mode, *band, *key_mgmt; + const char *mode, *band, *key_mgmt; guint32 channel; NM80211ApSecurityFlags flags; gboolean psk = FALSE, eap = FALSE, adhoc = FALSE; @@ -845,7 +845,7 @@ error: static void finalize(GObject *object) { - NMWifiAP * self = NM_WIFI_AP(object); + NMWifiAP *self = NM_WIFI_AP(object); NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(self); nm_assert(!self->wifi_device); @@ -890,7 +890,7 @@ nm_wifi_ap_class_init(NMWifiAPClass *ap_class) | NM_802_11_AP_SEC_KEY_MGMT_SAE | NM_802_11_AP_SEC_KEY_MGMT_OWE \ | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM | NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) - GObjectClass * object_class = G_OBJECT_CLASS(ap_class); + GObjectClass *object_class = G_OBJECT_CLASS(ap_class); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(ap_class); g_type_class_add_private(object_class, sizeof(NMWifiAPPrivate)); @@ -987,10 +987,10 @@ nm_wifi_ap_class_init(NMWifiAPClass *ap_class) const char ** nm_wifi_aps_get_paths(const CList *aps_lst_head, gboolean include_without_ssid) { - NMWifiAP * ap; + NMWifiAP *ap; gsize i, n; const char **list; - const char * path; + const char *path; n = c_list_length(aps_lst_head); list = g_new(const char *, n + 1); diff --git a/src/core/devices/wifi/nm-wifi-ap.h b/src/core/devices/wifi/nm-wifi-ap.h index bffd28a8..c0422900 100644 --- a/src/core/devices/wifi/nm-wifi-ap.h +++ b/src/core/devices/wifi/nm-wifi-ap.h @@ -32,9 +32,9 @@ typedef struct { NMDBusObject parent; - NMDevice * wifi_device; + NMDevice *wifi_device; CList aps_lst; - NMRefString * _supplicant_path; + NMRefString *_supplicant_path; struct _NMWifiAPPrivate *_priv; } NMWifiAP; @@ -47,15 +47,15 @@ GType nm_wifi_ap_get_type(void); NMWifiAP *nm_wifi_ap_new_from_properties(const struct _NMSupplicantBssInfo *bss_info); NMWifiAP *nm_wifi_ap_new_fake_from_connection(NMConnection *connection); -gboolean nm_wifi_ap_update_from_properties(NMWifiAP * ap, +gboolean nm_wifi_ap_update_from_properties(NMWifiAP *ap, const struct _NMSupplicantBssInfo *bss_info); gboolean nm_wifi_ap_check_compatible(NMWifiAP *self, NMConnection *connection); -gboolean nm_wifi_ap_complete_connection(NMWifiAP * self, +gboolean nm_wifi_ap_complete_connection(NMWifiAP *self, NMConnection *connection, gboolean lock_bssid, - GError ** error); + GError **error); static inline NMRefString * nm_wifi_ap_get_supplicant_path(NMWifiAP *ap) @@ -65,9 +65,9 @@ nm_wifi_ap_get_supplicant_path(NMWifiAP *ap) return ap->_supplicant_path; } -GBytes * nm_wifi_ap_get_ssid(const NMWifiAP *ap); +GBytes *nm_wifi_ap_get_ssid(const NMWifiAP *ap); gboolean nm_wifi_ap_set_ssid(NMWifiAP *ap, GBytes *ssid); -const char * nm_wifi_ap_get_address(const NMWifiAP *ap); +const char *nm_wifi_ap_get_address(const NMWifiAP *ap); gboolean nm_wifi_ap_set_address(NMWifiAP *ap, const char *addr); gboolean nm_wifi_ap_set_address_bin(NMWifiAP *ap, const NMEtherAddr *addr); _NM80211Mode nm_wifi_ap_get_mode(NMWifiAP *ap); diff --git a/src/core/devices/wifi/nm-wifi-common.c b/src/core/devices/wifi/nm-wifi-common.c index d029ce7f..681d9cb5 100644 --- a/src/core/devices/wifi/nm-wifi-common.c +++ b/src/core/devices/wifi/nm-wifi-common.c @@ -56,17 +56,17 @@ _dispatch_request_scan(NMDevice *device, GVariant *options, GDBusMethodInvocatio } static void -impl_device_wifi_get_access_points(NMDBusObject * obj, +impl_device_wifi_get_access_points(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { gs_free const char **list = NULL; - GVariant * v; - const CList * all_aps; + GVariant *v; + const CList *all_aps; /* NOTE: this handler is called both for NMDevicwWifi and NMDeviceIwd. */ @@ -77,17 +77,17 @@ impl_device_wifi_get_access_points(NMDBusObject * obj, } static void -impl_device_wifi_get_all_access_points(NMDBusObject * obj, +impl_device_wifi_get_all_access_points(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { gs_free const char **list = NULL; - GVariant * v; - const CList * all_aps; + GVariant *v; + const CList *all_aps; /* NOTE: this handler is called both for NMDevicwWifi and NMDeviceIwd. */ @@ -98,13 +98,13 @@ impl_device_wifi_get_all_access_points(NMDBusObject * obj, } static void -impl_device_wifi_request_scan(NMDBusObject * obj, +impl_device_wifi_request_scan(NMDBusObject *obj, const NMDBusInterfaceInfoExtended *interface_info, - const NMDBusMethodInfoExtended * method_info, - GDBusConnection * connection, - const char * sender, - GDBusMethodInvocation * invocation, - GVariant * parameters) + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { gs_unref_variant GVariant *options = NULL; diff --git a/src/core/devices/wifi/nm-wifi-factory.c b/src/core/devices/wifi/nm-wifi-factory.c index d2269c74..5e354c6b 100644 --- a/src/core/devices/wifi/nm-wifi-factory.c +++ b/src/core/devices/wifi/nm-wifi-factory.c @@ -14,6 +14,8 @@ #include "nm-device-wifi-p2p.h" #include "nm-device-olpc-mesh.h" #include "nm-device-iwd.h" +#include "nm-device-iwd-p2p.h" +#include "nm-iwd-manager.h" #include "settings/nm-settings-connection.h" #include "libnm-platform/nm-platform.h" #include "nm-config.h" @@ -50,7 +52,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES( NM_SETTING_OLPC_MESH_SETTING_NAME)) G_MODULE_EXPORT NMDeviceFactory * - nm_device_factory_create(GError **error) +nm_device_factory_create(GError **error) { return g_object_new(NM_TYPE_WIFI_FACTORY, NULL); } @@ -67,15 +69,29 @@ p2p_device_created(NMDeviceWifi *device, NMDeviceWifiP2P *p2p_device, NMDeviceFa g_signal_emit_by_name(self, NM_DEVICE_FACTORY_DEVICE_ADDED, p2p_device); } +#if WITH_IWD +static void +iwd_p2p_device_added(NMIwdManager *iwd, + NMDeviceIwdP2P *p2p_device, + const char *phy_name, + NMDeviceFactory *self) +{ + nm_log_info(LOGD_PLATFORM | LOGD_WIFI, "Wi-Fi P2P device added on %s", phy_name); + + g_signal_emit_by_name(self, NM_DEVICE_FACTORY_DEVICE_ADDED, p2p_device); +} +#endif + static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { gs_free char *backend_free = NULL; - const char * backend; + const char *backend; + _NM80211Mode mode; g_return_val_if_fail(iface != NULL, NULL); g_return_val_if_fail(plink != NULL, NULL); @@ -85,6 +101,20 @@ create_device(NMDeviceFactory * factory, if (plink->type != NM_LINK_TYPE_WIFI) return nm_device_olpc_mesh_new(iface); + /* Ignore monitor-mode and other unhandled interface types. + * FIXME: keep TYPE_MONITOR devices in UNAVAILABLE state and manage + * them if/when they change to a handled type. + */ + mode = nm_platform_wifi_get_mode(NM_PLATFORM_GET, plink->ifindex); + if (!NM_IN_SET(mode, + _NM_802_11_MODE_INFRA, + _NM_802_11_MODE_ADHOC, + _NM_802_11_MODE_AP, + _NM_802_11_MODE_MESH)) { + *out_ignore = TRUE; + return NULL; + } + backend = nm_config_data_get_device_config_by_pllink(NM_CONFIG_GET_DATA, NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_BACKEND, plink, @@ -92,15 +122,17 @@ create_device(NMDeviceFactory * factory, NULL); backend = nm_strstrip_avoid_copy_a(300, backend, &backend_free); + if (!backend) + backend = "" NM_CONFIG_DEFAULT_WIFI_BACKEND; + nm_log_dbg(LOGD_PLATFORM | LOGD_WIFI, "(%s) config: backend is %s%s%s%s", iface, NM_PRINT_FMT_QUOTE_STRING(backend), WITH_IWD ? " (iwd support enabled)" : ""); - if (!backend || !g_ascii_strcasecmp(backend, "wpa_supplicant")) { - NMDevice * device; + if (!g_ascii_strcasecmp(backend, "wpa_supplicant")) { + NMDevice *device; _NMDeviceWifiCapabilities capabilities; - _NM80211Mode mode; if (!nm_platform_wifi_get_capabilities(NM_PLATFORM_GET, plink->ifindex, &capabilities)) { nm_log_warn(LOGD_PLATFORM | LOGD_WIFI, @@ -110,16 +142,6 @@ create_device(NMDeviceFactory * factory, return NULL; } - /* Ignore monitor-mode and other unhandled interface types. - * FIXME: keep TYPE_MONITOR devices in UNAVAILABLE state and manage - * them if/when they change to a handled type. - */ - mode = nm_platform_wifi_get_mode(NM_PLATFORM_GET, plink->ifindex); - if (mode == _NM_802_11_MODE_UNKNOWN) { - *out_ignore = TRUE; - return NULL; - } - device = nm_device_wifi_new(iface, capabilities); g_signal_connect_object(device, @@ -131,8 +153,23 @@ create_device(NMDeviceFactory * factory, return device; } #if WITH_IWD - else if (!g_ascii_strcasecmp(backend, "iwd")) + else if (!g_ascii_strcasecmp(backend, "iwd")) { + NMIwdManager *iwd = nm_iwd_manager_get(); + + if (!g_signal_handler_find(iwd, + G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + G_CALLBACK(iwd_p2p_device_added), + factory)) + g_signal_connect(iwd, + NM_IWD_MANAGER_P2P_DEVICE_ADDED, + G_CALLBACK(iwd_p2p_device_added), + factory); + return nm_device_iwd_new(iface); + } #endif nm_log_warn(LOGD_PLATFORM | LOGD_WIFI, diff --git a/src/core/devices/wifi/nm-wifi-p2p-peer.c b/src/core/devices/wifi/nm-wifi-p2p-peer.c index ac13952d..0a174270 100644 --- a/src/core/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.c @@ -18,6 +18,7 @@ #include "nm-setting-wireless.h" #include "nm-utils.h" #include "nm-wifi-utils.h" +#include "nm-iwd-manager.h" #include "libnm-platform/nm-platform.h" #include "supplicant/nm-supplicant-types.h" @@ -77,8 +78,8 @@ const char ** nm_wifi_p2p_peers_get_paths(const CList *peers_lst_head) { NMWifiP2PPeer *peer; - const char ** list; - const char * path; + const char **list; + const char *path; gsize i, n; n = c_list_length(peers_lst_head); @@ -100,14 +101,16 @@ nm_wifi_p2p_peers_get_paths(const CList *peers_lst_head) } NMWifiP2PPeer * -nm_wifi_p2p_peers_find_first_compatible(const CList *peers_lst_head, NMConnection *connection) +nm_wifi_p2p_peers_find_first_compatible(const CList *peers_lst_head, + NMConnection *connection, + gboolean check_wfd) { NMWifiP2PPeer *peer; g_return_val_if_fail(connection, NULL); c_list_for_each_entry (peer, peers_lst_head, peers_lst) { - if (nm_wifi_p2p_peer_check_compatible(peer, connection)) + if (nm_wifi_p2p_peer_check_compatible(peer, connection, check_wfd)) return peer; } return NULL; @@ -261,7 +264,7 @@ nm_wifi_p2p_peer_get_wfd_ies(const NMWifiP2PPeer *peer) gboolean nm_wifi_p2p_peer_set_wfd_ies(NMWifiP2PPeer *peer, GBytes *wfd_ies) { - NMWifiP2PPeerPrivate *priv; + NMWifiP2PPeerPrivate *priv; gs_unref_bytes GBytes *wfd_ies_old = NULL; g_return_val_if_fail(NM_IS_WIFI_P2P_PEER(peer), FALSE); @@ -419,12 +422,96 @@ nm_wifi_p2p_peer_update_from_properties(NMWifiP2PPeer *peer, const NMSupplicantP return changed; } +gboolean +nm_wifi_p2p_peer_update_from_iwd_object(NMWifiP2PPeer *peer, GDBusObject *obj) +{ + NMWifiP2PPeerPrivate *priv; + gboolean changed = FALSE; + nm_auto_ref_string NMRefString *peer_path = NULL; + gs_unref_object GDBusProxy *peer_proxy = NULL; + gs_unref_object GDBusProxy *wfd_proxy = NULL; + GVariant *value; + gs_unref_bytes GBytes *wfd_ies = NULL; + + g_return_val_if_fail(NM_IS_WIFI_P2P_PEER(peer), FALSE); + + peer_proxy = G_DBUS_PROXY(g_dbus_object_get_interface(obj, NM_IWD_P2P_PEER_INTERFACE)); + wfd_proxy = G_DBUS_PROXY(g_dbus_object_get_interface(obj, NM_IWD_P2P_WFD_INTERFACE)); + g_return_val_if_fail(peer_proxy, FALSE); + + peer_path = nm_ref_string_new(g_dbus_object_get_object_path(obj)); + priv = NM_WIFI_P2P_PEER_GET_PRIVATE(peer); + nm_assert(!priv->supplicant_path || priv->supplicant_path == peer_path); + + g_object_freeze_notify(G_OBJECT(peer)); + + if (!priv->supplicant_path) { + priv->supplicant_path = g_steal_pointer(&peer_path); + changed = TRUE; + } + + value = g_dbus_proxy_get_cached_property(peer_proxy, "Name"); + if (value && g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) + changed |= nm_wifi_p2p_peer_set_name(peer, g_variant_get_string(value, NULL)); + else + changed |= nm_wifi_p2p_peer_set_name(peer, ""); + nm_g_variant_unref(value); + + value = g_dbus_proxy_get_cached_property(peer_proxy, "Address"); + if (value && g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) + changed |= nm_wifi_p2p_peer_set_address(peer, g_variant_get_string(value, NULL)); + nm_g_variant_unref(value); + + if (wfd_proxy) { + NMIwdWfdInfo wfd = {}; + + value = g_dbus_proxy_get_cached_property(wfd_proxy, "Source"); + wfd.source = value && g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean(value); + nm_g_variant_unref(value); + + value = g_dbus_proxy_get_cached_property(wfd_proxy, "Sink"); + wfd.sink = value && g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean(value); + nm_g_variant_unref(value); + + value = g_dbus_proxy_get_cached_property(wfd_proxy, "Port"); + wfd.port = (value && g_variant_is_of_type(value, G_VARIANT_TYPE_UINT16)) + ? g_variant_get_uint16(value) + : 0; + nm_g_variant_unref(value); + + value = g_dbus_proxy_get_cached_property(wfd_proxy, "HasAudio"); + wfd.has_audio = value && g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean(value); + nm_g_variant_unref(value); + + value = g_dbus_proxy_get_cached_property(wfd_proxy, "HasUIBC"); + wfd.has_uibc = value && g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean(value); + nm_g_variant_unref(value); + + value = g_dbus_proxy_get_cached_property(wfd_proxy, "HasContentProtection"); + wfd.has_cp = value && g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN) + && g_variant_get_boolean(value); + nm_g_variant_unref(value); + + wfd_ies = nm_wifi_utils_build_wfd_ies(&wfd); + } + + changed |= nm_wifi_p2p_peer_set_wfd_ies(peer, wfd_ies); + + g_object_thaw_notify(G_OBJECT(peer)); + + return changed; +} + const char * nm_wifi_p2p_peer_to_string(const NMWifiP2PPeer *self, char *str_buf, gsize buf_len, gint32 now_s) { const NMWifiP2PPeerPrivate *priv; - const char * supplicant_id = "-"; - const char * export_path; + const char *supplicant_id = "-"; + const char *export_path; g_return_val_if_fail(NM_IS_WIFI_P2P_PEER(self), NULL); @@ -458,11 +545,11 @@ nm_wifi_p2p_peer_to_string(const NMWifiP2PPeer *self, char *str_buf, gsize buf_l } gboolean -nm_wifi_p2p_peer_check_compatible(NMWifiP2PPeer *self, NMConnection *connection) +nm_wifi_p2p_peer_check_compatible(NMWifiP2PPeer *self, NMConnection *connection, gboolean check_wfd) { NMWifiP2PPeerPrivate *priv; - NMSettingWifiP2P * s_wifi_p2p; - const char * hwaddr; + NMSettingWifiP2P *s_wifi_p2p; + const char *hwaddr; g_return_val_if_fail(NM_IS_WIFI_P2P_PEER(self), FALSE); g_return_val_if_fail(NM_IS_CONNECTION(connection), FALSE); @@ -478,6 +565,10 @@ nm_wifi_p2p_peer_check_compatible(NMWifiP2PPeer *self, NMConnection *connection) if (hwaddr && (!priv->address || !nm_utils_hwaddr_matches(hwaddr, -1, priv->address, -1))) return FALSE; + if (check_wfd && nm_setting_wifi_p2p_get_wfd_ies(s_wifi_p2p) + && !nm_wifi_p2p_peer_get_wfd_ies(self)) + return FALSE; + return TRUE; } @@ -486,7 +577,7 @@ nm_wifi_p2p_peer_check_compatible(NMWifiP2PPeer *self, NMConnection *connection) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMWifiP2PPeer * self = NM_WIFI_P2P_PEER(object); + NMWifiP2PPeer *self = NM_WIFI_P2P_PEER(object); NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE(self); switch (prop_id) { @@ -559,10 +650,21 @@ nm_wifi_p2p_peer_new_from_properties(const NMSupplicantPeerInfo *peer_info) return peer; } +NMWifiP2PPeer * +nm_wifi_p2p_peer_new_from_iwd_object(GDBusObject *obj) +{ + NMWifiP2PPeer *peer; + + /* TODO: Set the flags here */ + peer = g_object_new(NM_TYPE_WIFI_P2P_PEER, NULL); + nm_wifi_p2p_peer_update_from_iwd_object(peer, obj); + return peer; +} + static void finalize(GObject *object) { - NMWifiP2PPeer * self = NM_WIFI_P2P_PEER(object); + NMWifiP2PPeer *self = NM_WIFI_P2P_PEER(object); NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE(self); nm_assert(!self->wifi_device); @@ -613,7 +715,7 @@ static const NMDBusInterfaceInfoExtended interface_info_p2p_peer = { static void nm_wifi_p2p_peer_class_init(NMWifiP2PPeerClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); g_type_class_add_private(object_class, sizeof(NMWifiP2PPeerPrivate)); diff --git a/src/core/devices/wifi/nm-wifi-p2p-peer.h b/src/core/devices/wifi/nm-wifi-p2p-peer.h index ee4bfb53..5124d1de 100644 --- a/src/core/devices/wifi/nm-wifi-p2p-peer.h +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.h @@ -33,7 +33,7 @@ typedef struct { NMDBusObject parent; - NMDevice * wifi_device; + NMDevice *wifi_device; CList peers_lst; struct _NMWifiP2PPeerPrivate *_priv; } NMWifiP2PPeer; @@ -45,11 +45,15 @@ struct _NMSupplicantPeerInfo; GType nm_wifi_p2p_peer_get_type(void); NMWifiP2PPeer *nm_wifi_p2p_peer_new_from_properties(const struct _NMSupplicantPeerInfo *peer_info); +NMWifiP2PPeer *nm_wifi_p2p_peer_new_from_iwd_object(GDBusObject *obj); -gboolean nm_wifi_p2p_peer_update_from_properties(NMWifiP2PPeer * peer, +gboolean nm_wifi_p2p_peer_update_from_properties(NMWifiP2PPeer *peer, const struct _NMSupplicantPeerInfo *peer_info); +gboolean nm_wifi_p2p_peer_update_from_iwd_object(NMWifiP2PPeer *peer, GDBusObject *obj); -gboolean nm_wifi_p2p_peer_check_compatible(NMWifiP2PPeer *self, NMConnection *connection); +gboolean nm_wifi_p2p_peer_check_compatible(NMWifiP2PPeer *self, + NMConnection *connection, + gboolean check_wfd); const char *nm_wifi_p2p_peer_get_supplicant_path(NMWifiP2PPeer *peer); @@ -64,12 +68,12 @@ gboolean nm_wifi_p2p_peer_set_model_number(NMWifiP2PPeer *peer, const char *n const char *nm_wifi_p2p_peer_get_serial(const NMWifiP2PPeer *peer); gboolean nm_wifi_p2p_peer_set_serial(NMWifiP2PPeer *peer, const char *serial); -GBytes * nm_wifi_p2p_peer_get_wfd_ies(const NMWifiP2PPeer *peer); +GBytes *nm_wifi_p2p_peer_get_wfd_ies(const NMWifiP2PPeer *peer); gboolean nm_wifi_p2p_peer_set_wfd_ies(NMWifiP2PPeer *peer, GBytes *bytes); const char *const *nm_wifi_p2p_peer_get_groups(const NMWifiP2PPeer *peer); -const char * nm_wifi_p2p_peer_get_address(const NMWifiP2PPeer *peer); +const char *nm_wifi_p2p_peer_get_address(const NMWifiP2PPeer *peer); gboolean nm_wifi_p2p_peer_set_address(NMWifiP2PPeer *peer, const char *addr); gint8 nm_wifi_p2p_peer_get_strength(NMWifiP2PPeer *peer); gboolean nm_wifi_p2p_peer_set_strength(NMWifiP2PPeer *peer, gint8 strength); @@ -80,11 +84,12 @@ nm_wifi_p2p_peer_to_string(const NMWifiP2PPeer *self, char *str_buf, gsize buf_l const char **nm_wifi_p2p_peers_get_paths(const CList *peers_lst_head); -NMWifiP2PPeer *nm_wifi_p2p_peers_find_first_compatible(const CList * peers_lst_head, - NMConnection *connection); +NMWifiP2PPeer *nm_wifi_p2p_peers_find_first_compatible(const CList *peers_lst_head, + NMConnection *connection, + gboolean check_wfd); NMWifiP2PPeer *nm_wifi_p2p_peers_find_by_supplicant_path(const CList *peers_lst_head, - const char * path); + const char *path); NMWifiP2PPeer *nm_wifi_p2p_peer_lookup_for_device(NMDevice *device, const char *exported_path); diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index 4939e786..1a8204b0 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -41,9 +41,9 @@ verify_no_wep(NMSettingWirelessSecurity *s_wsec, const char *tag, GError **error static gboolean verify_leap(NMSettingWirelessSecurity *s_wsec, - NMSetting8021x * s_8021x, + NMSetting8021x *s_8021x, gboolean adhoc, - GError ** error) + GError **error) { const char *key_mgmt, *auth_alg, *leap_username; @@ -224,9 +224,9 @@ verify_no_wpa(NMSettingWirelessSecurity *s_wsec, const char *tag, GError **error static gboolean verify_dynamic_wep(NMSettingWirelessSecurity *s_wsec, - NMSetting8021x * s_8021x, + NMSetting8021x *s_8021x, gboolean adhoc, - GError ** error) + GError **error) { const char *key_mgmt, *auth_alg, *leap_username; @@ -303,11 +303,11 @@ verify_dynamic_wep(NMSettingWirelessSecurity *s_wsec, static gboolean verify_wpa_psk(NMSettingWirelessSecurity *s_wsec, - NMSetting8021x * s_8021x, + NMSetting8021x *s_8021x, gboolean adhoc, guint32 wpa_flags, guint32 rsn_flags, - GError ** error) + GError **error) { const char *key_mgmt, *auth_alg; @@ -400,10 +400,10 @@ verify_wpa_psk(NMSettingWirelessSecurity *s_wsec, static gboolean verify_wpa_eap(NMSettingWirelessSecurity *s_wsec, - NMSetting8021x * s_8021x, + NMSetting8021x *s_8021x, guint32 wpa_flags, guint32 rsn_flags, - GError ** error) + GError **error) { const char *key_mgmt, *auth_alg; gboolean is_wpa_eap = FALSE; @@ -465,9 +465,9 @@ verify_wpa_eap(NMSettingWirelessSecurity *s_wsec, static gboolean verify_adhoc(NMSettingWirelessSecurity *s_wsec, - NMSetting8021x * s_8021x, + NMSetting8021x *s_8021x, gboolean adhoc, - GError ** error) + GError **error) { const char *key_mgmt = NULL, *leap_username = NULL, *auth_alg = NULL; @@ -529,8 +529,8 @@ verify_adhoc(NMSettingWirelessSecurity *s_wsec, } gboolean -nm_wifi_utils_complete_connection(GBytes * ap_ssid, - const char * bssid, +nm_wifi_utils_complete_connection(GBytes *ap_ssid, + const char *bssid, _NM80211Mode ap_mode, guint32 ap_freq, guint32 ap_flags, @@ -538,13 +538,13 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, guint32 ap_rsn_flags, NMConnection *connection, gboolean lock_bssid, - GError ** error) + GError **error) { - NMSettingWireless * s_wifi; + NMSettingWireless *s_wifi; NMSettingWirelessSecurity *s_wsec; - NMSetting8021x * s_8021x; - GBytes * ssid; - const char * mode, *key_mgmt, *auth_alg, *leap_username; + NMSetting8021x *s_8021x; + GBytes *ssid; + const char *mode, *key_mgmt, *auth_alg, *leap_username; gboolean adhoc = FALSE; gboolean mesh = FALSE; @@ -892,20 +892,20 @@ nm_wifi_utils_is_manf_default_ssid(GBytes *ssid) /* To be used for connections where the SSID has been validated before */ gboolean -nm_wifi_connection_get_iwd_ssid_and_security(NMConnection * connection, - char ** ssid, +nm_wifi_connection_get_iwd_ssid_and_security(NMConnection *connection, + char **ssid, NMIwdNetworkSecurity *security) { - NMSettingWireless * s_wireless; + NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; - const char * key_mgmt = NULL; + const char *key_mgmt = NULL; s_wireless = nm_connection_get_setting_wireless(connection); if (!s_wireless) return FALSE; if (ssid) { - GBytes * bytes = nm_setting_wireless_get_ssid(s_wireless); + GBytes *bytes = nm_setting_wireless_get_ssid(s_wireless); gsize ssid_len; const char *ssid_str = (const char *) g_bytes_get_data(bytes, &ssid_len); @@ -947,7 +947,7 @@ nm_wifi_connection_get_iwd_ssid_and_security(NMConnection * connection, * @ssid_len can be -1 instead of actual SSID length. */ char * -nm_wifi_utils_get_iwd_config_filename(const char * ssid, +nm_wifi_utils_get_iwd_config_filename(const char *ssid, gssize ssid_len, NMIwdNetworkSecurity security) { @@ -995,10 +995,10 @@ static gboolean psk_setting_to_iwd_config(GKeyFile *file, NMSettingWirelessSecurity *s_wsec, GError **error) { NMSettingSecretFlags psk_flags = nm_setting_wireless_security_get_psk_flags(s_wsec); - const char * psk = nm_setting_wireless_security_get_psk(s_wsec); + const char *psk = nm_setting_wireless_security_get_psk(s_wsec); gsize psk_len; guint8 buffer[32]; - const char * key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wsec); + const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wsec); if (!psk || NM_FLAGS_ANY(psk_flags, SECRETS_DONT_STORE_FLAGS)) { if (NM_FLAGS_ANY(psk_flags, SECRETS_DONT_STORE_FLAGS)) { @@ -1029,11 +1029,11 @@ psk_setting_to_iwd_config(GKeyFile *file, NMSettingWirelessSecurity *s_wsec, GEr } static gboolean -eap_certs_to_iwd_config(GKeyFile * file, +eap_certs_to_iwd_config(GKeyFile *file, NMSetting8021x *s_8021x, bool phase2, - char * iwd_prefix, - GError ** error) + char *iwd_prefix, + GError **error) { NMSetting8021xCKScheme ca_cert_scheme = phase2 ? nm_setting_802_1x_get_phase2_ca_cert_scheme(s_8021x) @@ -1043,13 +1043,13 @@ eap_certs_to_iwd_config(GKeyFile * file, : nm_setting_802_1x_get_client_cert_scheme(s_8021x); NMSetting8021xCKScheme key_scheme; NMSettingSecretFlags key_password_flags; - const char * ca_path = phase2 ? nm_setting_802_1x_get_phase2_ca_path(s_8021x) + const char *ca_path = phase2 ? nm_setting_802_1x_get_phase2_ca_path(s_8021x) : nm_setting_802_1x_get_ca_path(s_8021x); - const char * cert_path; - const char * key_path = NULL; - const char * key_password; - const char * domain_suffix_match; - const char * domain_match; + const char *cert_path; + const char *key_path = NULL; + const char *key_password; + const char *domain_suffix_match; + const char *domain_match; char setting_buf[128]; /* TODO: should check that all certificates and the key are RSA */ @@ -1220,7 +1220,7 @@ private_key_done: : nm_setting_802_1x_get_domain_match(s_8021x); if (domain_suffix_match || domain_match) { - GString * s = g_string_sized_new(128); + GString *s = g_string_sized_new(128); const char *ptr; const char *end; @@ -1287,13 +1287,13 @@ eap_optional_identity_to_iwd_config(GKeyFile *file, const char *iwd_prefix, cons } static gboolean -eap_optional_password_to_iwd_config(GKeyFile * file, - const char * iwd_prefix, +eap_optional_password_to_iwd_config(GKeyFile *file, + const char *iwd_prefix, NMSetting8021x *s_8021x, - GError ** error) + GError **error) { char setting_buf[128]; - const char * password = nm_setting_802_1x_get_password(s_8021x); + const char *password = nm_setting_802_1x_get_password(s_8021x); NMSettingSecretFlags flags = nm_setting_802_1x_get_password_flags(s_8021x); if (!password && nm_setting_802_1x_get_password_raw(s_8021x)) { @@ -1347,12 +1347,12 @@ eap_phase1_identity_to_iwd_config(GKeyFile *file, const char *iwd_prefix, NMSett } static gboolean -eap_method_config_to_iwd_config(GKeyFile * file, +eap_method_config_to_iwd_config(GKeyFile *file, NMSetting8021x *s_8021x, gboolean phase2, - const char * method, - const char * iwd_prefix, - GError ** error) + const char *method, + const char *iwd_prefix, + GError **error) { char prefix_buf[128]; @@ -1677,18 +1677,18 @@ ip6_config_to_iwd_config(GKeyFile *file, NMSettingIPConfig *s_ip, GError **error GKeyFile * nm_wifi_utils_connection_to_iwd_config(NMConnection *connection, - char ** out_filename, - GError ** error) + char **out_filename, + GError **error) { - NMSettingConnection * s_conn = nm_connection_get_setting_connection(connection); - NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(connection); - GBytes * ssid; - const guint8 * ssid_data; - gsize ssid_len; - NMIwdNetworkSecurity security; - const char * cloned_mac_addr; - gs_free char * comment = NULL; - nm_auto_unref_keyfile GKeyFile *file = NULL; + NMSettingConnection *s_conn = nm_connection_get_setting_connection(connection); + NMSettingWireless *s_wifi = nm_connection_get_setting_wireless(connection); + GBytes *ssid; + const guint8 *ssid_data; + gsize ssid_len; + NMIwdNetworkSecurity security; + const char *cloned_mac_addr; + gs_free char *comment = NULL; + nm_auto_unref_keyfile GKeyFile *file = NULL; if (!s_conn || !s_wifi || !nm_streq(nm_setting_connection_get_connection_type(s_conn), @@ -1800,3 +1800,151 @@ nm_wifi_utils_connection_to_iwd_config(NMConnection *connection, return g_steal_pointer(&file); } + +/* Wi-Fi Display Technical Specification v2.1.0 Table 27 */ +enum wfd_subelem_type { + WFD_SUBELEM_WFD_DEVICE_INFORMATION = 0, + WFD_SUBELEM_ASSOCIATED_BSSID = 1, + WFD_SUBELEM_COUPLED_SINK_INFORMATION = 6, + WFD_SUBELEM_EXTENDED_CAPABILITY = 7, + WFD_SUBELEM_LOCAL_IP_ADDRESS = 8, + WFD_SUBELEM_SESION_INFORMATION = 9, + WFD_SUBELEM_ALTERNATIVE_MAC_ADDRESS = 10, + WFD_SUBELEM_R2_DEVICE_INFORMATION = 11, +}; + +bool +nm_wifi_utils_parse_wfd_ies(GBytes *ies, NMIwdWfdInfo *out_wfd) +{ + size_t len; + const uint8_t *data = g_bytes_get_data(ies, &len); + const uint8_t *dev_info = NULL; + uint16_t dev_info_len = 0; + uint16_t dev_info_flags; + const uint8_t *ext_capability = NULL; + uint16_t ext_capability_len = 0; + + /* The single WFD IEs array provided by the client is supposed to be sent to + * the peer in the different frame types that may include the WFD IE: Probe + * Request/Response, Beacon, (Re)Association Request/Response, GO + * Negotiation Request/Response/Confirm and Provision Discovery + * Request/Response. + * + * It's going to be a subset of the elements allowed in all those frames. + * Validate that it contains at least a valid WFD Device Information (with + * the Session Available bit true) and that the sequence of subelements is + * valid. + */ + while (len) { + uint8_t subelem_id; + uint16_t subelem_len; + + /* Does the subelement header fit */ + if (len < 3) + return FALSE; + + subelem_id = data[0]; + subelem_len = (data[1] << 8) | data[2]; + data += 3; + len -= 3; + + if (subelem_len > len) + return FALSE; + + if (subelem_id == WFD_SUBELEM_WFD_DEVICE_INFORMATION) { + /* Is there a duplicate WFD Device Information */ + if (dev_info) + return FALSE; + + dev_info = data; + dev_info_len = subelem_len; + } + + if (subelem_id == WFD_SUBELEM_EXTENDED_CAPABILITY) { + /* Is there a duplicate WFD Extended Capability */ + if (ext_capability) + return FALSE; + + ext_capability = data; + ext_capability_len = subelem_len; + } + + data += subelem_len; + len -= subelem_len; + } + + if (!dev_info || dev_info_len != 6) + return FALSE; + + dev_info_flags = (dev_info[0] << 8) | dev_info[1]; + + /* Secondary sink not supported */ + if ((dev_info_flags & 3) == 2) + return FALSE; + + /* Must be available for WFD Session */ + if (((dev_info_flags >> 4) & 3) != 1) + return FALSE; + + /* TDLS persistent group re-invocation not supported */ + if ((dev_info_flags >> 13) & 1) + return FALSE; + + /* All other flags indicate support but not a requirement for something + * so not preserving them in the IEs IWD eventually sends doesn't break + * basic functionality. + */ + + if (ext_capability && ext_capability_len != 2) + return FALSE; + + if (!out_wfd) + return TRUE; + + out_wfd->source = NM_IN_SET(dev_info_flags & 3, 0, 3); + out_wfd->sink = NM_IN_SET(dev_info_flags & 3, 1, 3); + out_wfd->port = (dev_info[2] << 8) | dev_info[3]; + out_wfd->has_audio = + out_wfd->sink ? ((dev_info_flags >> 10) & 1) == 0 : (((dev_info_flags >> 11) & 1) == 1); + out_wfd->has_uibc = ext_capability && (ext_capability[1] & 1) == 1; + out_wfd->has_cp = ((dev_info_flags >> 8) & 1) == 1; + return TRUE; +} + +GBytes * +nm_wifi_utils_build_wfd_ies(const NMIwdWfdInfo *wfd) +{ + uint8_t data[64]; + uint8_t *ptr = data; + + *ptr++ = WFD_SUBELEM_WFD_DEVICE_INFORMATION; + *ptr++ = 0; /* WFD Subelement length */ + *ptr++ = 6; + *ptr++ = 0; /* WFD Device Information bitmap: */ + *ptr++ = (wfd->source ? (wfd->sink ? 3 : 0) : 1) | 0x10 | /* WFD Session Available */ + (wfd->has_cp ? 0x100 : 0) | (wfd->has_audio ? 0 : 0x400); + *ptr++ = wfd->port >> 8; + *ptr++ = wfd->port & 255; + *ptr++ = 0; /* WFD Device Maximum throughput */ + *ptr++ = 10; + + if (wfd->has_uibc) { + *ptr++ = WFD_SUBELEM_EXTENDED_CAPABILITY; + *ptr++ = 0; /* WFD Subelement length */ + *ptr++ = 2; + *ptr++ = 0x00; /* WFD Extended Capability Bitmap: */ + *ptr++ = 0x10; /* UIBC Support */ + } + + return g_bytes_new(data, ptr - data); +} + +bool +nm_wifi_utils_wfd_info_eq(const NMIwdWfdInfo *a, const NMIwdWfdInfo *b) +{ + if (!a || !b) + return a == b; + + return a->source == b->source && a->sink == b->sink && a->port == b->port + && a->has_audio == b->has_audio && a->has_uibc == b->has_uibc && a->has_cp == b->has_cp; +} diff --git a/src/core/devices/wifi/nm-wifi-utils.h b/src/core/devices/wifi/nm-wifi-utils.h index 2664c03e..1d46a900 100644 --- a/src/core/devices/wifi/nm-wifi-utils.h +++ b/src/core/devices/wifi/nm-wifi-utils.h @@ -20,8 +20,17 @@ typedef enum { NM_IWD_NETWORK_SECURITY_8021X, } NMIwdNetworkSecurity; -gboolean nm_wifi_utils_complete_connection(GBytes * ssid, - const char * bssid, +typedef struct { + bool source; + bool sink; + uint16_t port; + bool has_audio; + bool has_uibc; + bool has_cp; +} NMIwdWfdInfo; + +gboolean nm_wifi_utils_complete_connection(GBytes *ssid, + const char *bssid, _NM80211Mode mode, guint32 ap_freq, guint32 flags, @@ -29,18 +38,22 @@ gboolean nm_wifi_utils_complete_connection(GBytes * ssid, guint32 rsn_flags, NMConnection *connection, gboolean lock_bssid, - GError ** error); + GError **error); gboolean nm_wifi_utils_is_manf_default_ssid(GBytes *ssid); -gboolean nm_wifi_connection_get_iwd_ssid_and_security(NMConnection * connection, - char ** ssid, +gboolean nm_wifi_connection_get_iwd_ssid_and_security(NMConnection *connection, + char **ssid, NMIwdNetworkSecurity *security); -char * nm_wifi_utils_get_iwd_config_filename(const char * ssid, +char *nm_wifi_utils_get_iwd_config_filename(const char *ssid, gssize ssid_len, NMIwdNetworkSecurity security); GKeyFile * nm_wifi_utils_connection_to_iwd_config(NMConnection *conn, char **out_filename, GError **error); +bool nm_wifi_utils_parse_wfd_ies(GBytes *ies, NMIwdWfdInfo *out_wfd); +GBytes *nm_wifi_utils_build_wfd_ies(const NMIwdWfdInfo *wfd); +bool nm_wifi_utils_wfd_info_eq(const NMIwdWfdInfo *a, const NMIwdWfdInfo *b); + #endif /* __NM_WIFI_UTILS_H__ */ diff --git a/src/core/devices/wifi/tests/test-devices-wifi.c b/src/core/devices/wifi/tests/test-devices-wifi.c index 5d1167cf..69d365e3 100644 --- a/src/core/devices/wifi/tests/test-devices-wifi.c +++ b/src/core/devices/wifi/tests/test-devices-wifi.c @@ -47,18 +47,18 @@ } static gboolean -complete_connection(const char * ssid, - const char * bssid, +complete_connection(const char *ssid, + const char *bssid, _NM80211Mode mode, guint32 flags, guint32 wpa_flags, guint32 rsn_flags, gboolean lock_bssid, NMConnection *src, - GError ** error) + GError **error) { gs_unref_bytes GBytes *ssid_b = NULL; - NMSettingWireless * s_wifi; + NMSettingWireless *s_wifi; /* Add a wifi setting if one doesn't exist */ s_wifi = nm_connection_get_setting_wireless(src); @@ -91,8 +91,8 @@ static void set_items(NMSetting *setting, const KeyData *items) { const KeyData *item; - GParamSpec * pspec; - GBytes * tmp; + GParamSpec *pspec; + GBytes *tmp; for (item = items; item && item->key; item++) { g_assert(item->key); @@ -199,9 +199,9 @@ fill_8021x(NMConnection *connection, const KeyData items[]) static NMConnection * create_basic(const char *ssid, const char *bssid, _NM80211Mode mode) { - NMConnection * connection; + NMConnection *connection; NMSettingWireless *s_wifi = NULL; - GBytes * tmp; + GBytes *tmp; connection = nm_simple_connection_new(); @@ -233,10 +233,10 @@ static void test_lock_bssid(void) { NMConnection *src, *expected; - const char * bssid = "01:02:03:04:05:06"; - const char * ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; + const char *ssid = "blahblah"; gboolean success; - GError * error = NULL; + GError *error = NULL; src = nm_simple_connection_new(); success = complete_connection(ssid, @@ -261,10 +261,10 @@ static void test_open_ap_empty_connection(void) { NMConnection *src, *expected; - const char * bssid = "01:02:03:04:05:06"; - const char * ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; + const char *ssid = "blahblah"; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that an empty source connection is correctly filled with the * SSID and Infra modes of the given AP details. @@ -293,11 +293,11 @@ static void test_open_ap_leap_connection_1(gconstpointer add_wifi) { NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "Bill Smith", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that a basic connection filled with a LEAP username is * rejected when completion is attempted with an open AP. LEAP requires @@ -330,10 +330,10 @@ static void test_open_ap_leap_connection_2(void) { NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that a basic connection specifying IEEE8021x security (ie, Dynamic * WEP or LEAP) is rejected when completion is attempted with an open AP. @@ -364,14 +364,14 @@ static void test_open_ap_wep_connection(gconstpointer add_wifi) { NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = { {NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "11111111111111111111111111", 0}, {NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, NULL, 0}, {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that a static WEP connection is rejected when completion is * attempted with an open AP. @@ -399,8 +399,8 @@ test_open_ap_wep_connection(gconstpointer add_wifi) /*****************************************************************************/ static void -test_ap_wpa_psk_connection_base(const char * key_mgmt, - const char * auth_alg, +test_ap_wpa_psk_connection_base(const char *key_mgmt, + const char *auth_alg, guint32 flags, guint32 wpa_flags, guint32 rsn_flags, @@ -409,8 +409,8 @@ test_ap_wpa_psk_connection_base(const char * key_mgmt, NMConnection *expected) { NMConnection *src; - const char * ssid = "blahblah"; - const char * bssid = "01:02:03:04:05:06"; + const char *ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; const KeyData exp_wifi[] = {{NM_SETTING_WIRELESS_SSID, ssid, 0}, {NM_SETTING_WIRELESS_MODE, "infrastructure", 0}, {NULL}}; @@ -419,7 +419,7 @@ test_ap_wpa_psk_connection_base(const char * key_mgmt, {NM_SETTING_WIRELESS_SECURITY_PSK, "asdfasdfasdfasdfasdfafs", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; src = nm_simple_connection_new(); if (add_wifi) @@ -538,13 +538,13 @@ test_ap_wpa_eap_connection_base(const char *key_mgmt, guint error_code) { NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_empty[] = {{NULL}}; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, key_mgmt, 0}, {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, auth_alg, 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; src = nm_simple_connection_new(); if (add_wifi) @@ -738,11 +738,11 @@ static void test_priv_ap_empty_connection(void) { NMConnection *src, *expected; - const char * bssid = "01:02:03:04:05:06"; - const char * ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; + const char *ssid = "blahblah"; const KeyData exp_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that an empty connection is completed to a valid Static WEP * connection when completed with an AP with the Privacy bit set. @@ -774,9 +774,9 @@ static void test_priv_ap_leap_connection_1(gconstpointer add_wifi) { NMConnection *src, *expected; - const char * ssid = "blahblah"; - const char * bssid = "01:02:03:04:05:06"; - const char * leap_username = "Bill Smith"; + const char *ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; + const char *leap_username = "Bill Smith"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, {NULL}}; @@ -785,7 +785,7 @@ test_priv_ap_leap_connection_1(gconstpointer add_wifi) {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that an minimal LEAP connection specifying only key management and * the LEAP username is completed to a full LEAP connection when completed @@ -823,12 +823,12 @@ static void test_priv_ap_leap_connection_2(void) { NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that an minimal LEAP connection specifying only key management and * the LEAP auth alg is completed to a full LEAP connection when completed @@ -859,8 +859,8 @@ static void test_priv_ap_dynamic_wep_1(void) { NMConnection *src, *expected; - const char * ssid = "blahblah"; - const char * bssid = "01:02:03:04:05:06"; + const char *ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, {NULL}}; @@ -872,7 +872,7 @@ test_priv_ap_dynamic_wep_1(void) {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that an minimal Dynamic WEP connection specifying key management, * the auth algorithm, and valid 802.1x setting is completed to a valid @@ -909,8 +909,8 @@ static void test_priv_ap_dynamic_wep_2(void) { NMConnection *src, *expected; - const char * ssid = "blahblah"; - const char * bssid = "01:02:03:04:05:06"; + const char *ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, {NULL}}; const KeyData both_8021x[] = {{NM_SETTING_802_1X_EAP, "peap", 0}, {NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0}, @@ -920,7 +920,7 @@ test_priv_ap_dynamic_wep_2(void) {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that an minimal Dynamic WEP connection specifying only the auth * algorithm and a valid 802.1x setting is completed to a valid Dynamic @@ -957,14 +957,14 @@ static void test_priv_ap_dynamic_wep_3(void) { NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", 0}, {NULL}}; const KeyData src_8021x[] = {{NM_SETTING_802_1X_EAP, "peap", 0}, {NM_SETTING_802_1X_IDENTITY, "Bill Smith", 0}, {NM_SETTING_802_1X_PHASE2_AUTH, "mschapv2", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Ensure that a basic connection specifying 'shared' auth and an 802.1x * setting is rejected, as 802.1x is incompatible with 'shared' auth. @@ -1086,13 +1086,13 @@ test_wpa_ap_empty_connection(gconstpointer data) { guint idx = GPOINTER_TO_UINT(data); NMConnection *src, *expected; - const char * bssid = "01:02:03:04:05:06"; - const char * ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; + const char *ssid = "blahblah"; const KeyData exp_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", 0}, {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that a basic WPA-PSK connection specifying just key management and * the auth algorithm is completed successfully when given an AP with WPA @@ -1126,14 +1126,14 @@ test_wpa_ap_leap_connection_1(gconstpointer data) { guint idx = GPOINTER_TO_UINT(data); NMConnection *src; - const char * ssid = "blahblah"; - const char * bssid = "01:02:03:04:05:06"; - const char * leap_username = "Bill Smith"; + const char *ssid = "blahblah"; + const char *bssid = "01:02:03:04:05:06"; + const char *leap_username = "Bill Smith"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, {NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username, 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that completion of a LEAP connection with a WPA-enabled AP is * rejected since WPA APs (usually) do not support LEAP. @@ -1164,12 +1164,12 @@ test_wpa_ap_leap_connection_2(gconstpointer data) { guint idx = GPOINTER_TO_UINT(data); NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, {NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that completion of a LEAP connection with a WPA-enabled AP is * rejected since WPA APs (usually) do not support LEAP. @@ -1200,10 +1200,10 @@ test_wpa_ap_dynamic_wep_connection(gconstpointer data) { guint idx = GPOINTER_TO_UINT(data); NMConnection *src; - const char * bssid = "01:02:03:04:05:06"; + const char *bssid = "01:02:03:04:05:06"; const KeyData src_wsec[] = {{NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", 0}, {NULL}}; gboolean success; - GError * error = NULL; + GError *error = NULL; /* Test that completion of a Dynamic WEP connection with a WPA-enabled AP is * rejected since WPA APs (usually) do not support Dynamic WEP. @@ -1409,12 +1409,12 @@ test_strength_all(void) static void do_test_ssids_options_to_ptrarray(const char *const *ssids) { - GVariantBuilder builder; - gs_unref_variant GVariant *variant = NULL; + GVariantBuilder builder; + gs_unref_variant GVariant *variant = NULL; gs_unref_ptrarray GPtrArray *ssids_arr = NULL; - gs_free_error GError *error = NULL; - gsize len; - gsize i; + gs_free_error GError *error = NULL; + gsize len; + gsize i; g_assert(ssids); @@ -1443,7 +1443,7 @@ do_test_ssids_options_to_ptrarray(const char *const *ssids) g_assert_cmpint(len, ==, ssids_arr->len); for (i = 0; i < len; i++) { const char *ssid = ssids[i]; - GBytes * bytes = ssids_arr->pdata[i]; + GBytes *bytes = ssids_arr->pdata[i]; g_assert(nm_g_bytes_equal_mem(bytes, ssid, strlen(ssid))); } diff --git a/src/core/devices/wwan/libnm-wwan.ver b/src/core/devices/wwan/libnm-wwan.ver index c368a590..640df36d 100644 --- a/src/core/devices/wwan/libnm-wwan.ver +++ b/src/core/devices/wwan/libnm-wwan.ver @@ -14,7 +14,6 @@ global: nm_modem_get_control_port; nm_modem_get_device_id; nm_modem_get_driver; - nm_modem_get_iid; nm_modem_get_ip_ifindex; nm_modem_get_operator_code; nm_modem_get_path; @@ -22,7 +21,6 @@ global: nm_modem_get_state; nm_modem_get_type; nm_modem_get_uid; - nm_modem_ip4_pre_commit; nm_modem_is_claimed; nm_modem_manager_get; nm_modem_manager_get_modems; @@ -32,8 +30,7 @@ global: nm_modem_manager_name_owner_unref; nm_modem_owns_port; nm_modem_set_mm_enabled; - nm_modem_stage3_ip4_config_start; - nm_modem_stage3_ip6_config_start; + nm_modem_stage3_ip_config_start; nm_modem_state_to_string; nm_modem_unclaim; local: diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c index 1b285469..ef802a44 100644 --- a/src/core/devices/wwan/nm-device-modem.c +++ b/src/core/devices/wwan/nm-device-modem.c @@ -8,7 +8,7 @@ #include "nm-device-modem.h" #include "nm-modem.h" -#include "nm-ip4-config.h" +#include "nm-l3-config-data.h" #include "devices/nm-device-private.h" #include "nm-rfkill-manager.h" #include "settings/nm-settings-connection.h" @@ -30,14 +30,16 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceModem, PROP_APN, ); typedef struct { - NMModem * modem; + NMModem *modem; NMDeviceModemCapabilities caps; NMDeviceModemCapabilities current_caps; - char * device_id; - char * operator_code; - char * apn; + NMUtilsIPv6IfaceId iid; + char *device_id; + char *operator_code; + char *apn; bool rf_enabled : 1; NMDeviceStageState stage1_state : 3; + NMDeviceStageState stage2_state : 3; } NMDeviceModemPrivate; struct _NMDeviceModem { @@ -59,52 +61,18 @@ G_DEFINE_TYPE(NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) static void ppp_failed(NMModem *modem, guint i_reason, gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceStateReason reason = i_reason; - switch (nm_device_get_state(device)) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); - break; - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_IP_CHECK: - case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: - if (nm_device_activate_ip4_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET); - else if (nm_device_activate_ip6_state_in_conf(device)) - nm_device_activate_schedule_ip_config_timeout(device, AF_INET6); - else if (nm_device_activate_ip4_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else if (nm_device_activate_ip6_state_done(device)) { - nm_device_ip_method_failed(device, - AF_INET6, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } else { - _LOGW(LOGD_MB, - "PPP failure in unexpected state %u", - (guint) nm_device_get_state(device)); - nm_device_state_changed(device, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - break; - default: - break; - } + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); } static void modem_prepare_result(NMModem *modem, gboolean success, guint i_reason, gpointer user_data) { - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); + NMDevice *device = NM_DEVICE(self); NMDeviceStateReason reason = i_reason; if (nm_device_get_state(device) != NM_DEVICE_STATE_PREPARE @@ -173,7 +141,7 @@ modem_auth_requested(NMModem *modem, gpointer user_data) static void modem_auth_result(NMModem *modem, GError *error, gpointer user_data) { - NMDevice * device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); g_return_if_fail(nm_device_get_state(device) == NM_DEVICE_STATE_NEED_AUTH); @@ -188,102 +156,50 @@ modem_auth_result(NMModem *modem, GError *error, gpointer user_data) } static void -modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data) -{ - NMDeviceModem *self = NM_DEVICE_MODEM(user_data); - NMDevice * device = NM_DEVICE(self); - - if (!nm_device_activate_ip4_state_in_conf(device)) { - _LOGD(LOGD_MB | LOGD_IP4, - "retrieving IPv4 configuration while no longer in state IPv4 conf"); +modem_new_config(NMModem *modem, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid, + int failure_reason_i, + GError *error, + gpointer user_data) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); + NMDevice *device = NM_DEVICE(self); + + if (nm_device_devip_get_state(device, addr_family) != NM_DEVICE_IP_STATE_PENDING) { + _LOGD(LOGD_MB, "retrieving IP configuration while no longer in pending state"); return; } if (error) { - _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message); - nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - - nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config)); - nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL); -} - -static void -modem_ip6_config_result(NMModem * modem, - NMIP6Config *config, - gboolean do_slaac, - GError * error, - gpointer user_data) -{ - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); - NMDevice * device = NM_DEVICE(self); - NMActStageReturn ret; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - gs_unref_object NMIP6Config *ignored = NULL; - gboolean got_config = !!config; - - if (!nm_device_activate_ip6_state_in_conf(device)) { - _LOGD(LOGD_MB | LOGD_IP6, - "retrieving IPv6 configuration while no longer in state IPv6 conf"); + _LOGW(LOGD_MB, "retrieving IP configuration failed: %s", error->message); + nm_device_devip_set_failed(device, addr_family, failure_reason_i); return; } - if (error) { - _LOGW(LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message); - nm_device_ip_method_failed(device, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } + if (!IS_IPv4) + priv->iid = iid ? *iid : ((NMUtilsIPv6IfaceId) NM_UTILS_IPV6_IFACE_ID_INIT); - /* Re-enable IPv6 on the interface */ - nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0"); - - if (config) - nm_device_set_dev2_ip_config(device, AF_INET6, NM_IP_CONFIG_CAST(config)); - - if (do_slaac == FALSE) { - if (got_config) - nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL); - else { - _LOGW(LOGD_MB | LOGD_IP6, - "retrieving IPv6 configuration failed: SLAAC not requested and no addresses"); - nm_device_ip_method_failed(device, - AF_INET6, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - } - return; + if (do_auto) { + if (IS_IPv4) + nm_device_ip_method_dhcp4_start(device); + else + nm_device_ip_method_autoconf6_start(device); } - /* Start SLAAC now that we have a link-local address from the modem */ - ret = - NM_DEVICE_CLASS(nm_device_modem_parent_class) - ->act_stage3_ip_config_start(device, AF_INET6, (gpointer *) &ignored, &failure_reason); - - nm_assert(ignored == NULL); - - switch (ret) { - case NM_ACT_STAGE_RETURN_FAILURE: - nm_device_ip_method_failed(device, AF_INET6, failure_reason); - break; - case NM_ACT_STAGE_RETURN_IP_FAIL: - /* all done */ - nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL); - break; - case NM_ACT_STAGE_RETURN_POSTPONE: - /* let SLAAC run */ - break; - default: - /* Should never get here since we've assured that the IPv6 method - * will either be "auto" or "ignored" when starting IPv6 configuration. - */ - nm_assert_not_reached(); - } + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd); } static void ip_ifindex_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDevice *device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(device); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); if (!nm_device_is_activating(device)) return; @@ -300,14 +216,19 @@ ip_ifindex_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) * RA handling code to run before NM is ready. */ nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "1"); + + if (priv->stage2_state == NM_DEVICE_STAGE_STATE_PENDING) { + priv->stage2_state = NM_DEVICE_STAGE_STATE_COMPLETED; + nm_device_activate_schedule_stage2_device_config(device, FALSE); + } } static void operator_code_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - const char * operator_code = nm_modem_get_operator_code(modem); + const char *operator_code = nm_modem_get_operator_code(modem); if (g_strcmp0(priv->operator_code, operator_code) != 0) { g_free(priv->operator_code); @@ -319,9 +240,9 @@ operator_code_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) static void apn_changed_cb(NMModem *modem, GParamSpec *pspec, gpointer user_data) { - NMDeviceModem * self = NM_DEVICE_MODEM(user_data); + NMDeviceModem *self = NM_DEVICE_MODEM(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - const char * apn = nm_modem_get_apn(modem); + const char *apn = nm_modem_get_apn(modem); if (g_strcmp0(priv->apn, apn) != 0) { g_free(priv->apn); @@ -341,7 +262,7 @@ modem_state_cb(NMModem *modem, int new_state_i, int old_state_i, gpointer user_d { NMModemState new_state = new_state_i; NMModemState old_state = old_state_i; - NMDevice * device = NM_DEVICE(user_data); + NMDevice *device = NM_DEVICE(user_data); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); NMDeviceState dev_state = nm_device_get_state(device); @@ -413,12 +334,12 @@ owns_iface(NMDevice *device, const char *iface) /*****************************************************************************/ static void -device_state_changed(NMDevice * device, +device_state_changed(NMDevice *device, NMDeviceState new_state, NMDeviceState old_state, NMDeviceStateReason reason) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); g_return_if_fail(priv->modem); @@ -480,13 +401,13 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * } static gboolean -check_connection_available(NMDevice * device, - NMConnection * connection, +check_connection_available(NMDevice *device, + NMConnection *connection, NMDeviceCheckConAvailableFlags flags, - const char * specific_object, - GError ** error) + const char *specific_object, + GError **error) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); NMModemState state; @@ -525,11 +446,11 @@ check_connection_available(NMDevice * device, } static gboolean -complete_connection(NMDevice * device, - NMConnection * connection, - const char * specific_object, +complete_connection(NMDevice *device, + NMConnection *connection, + const char *specific_object, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); @@ -547,6 +468,7 @@ deactivate(NMDevice *device) nm_modem_deactivate(priv->modem, device); priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT; + priv->stage2_state = NM_DEVICE_STAGE_STATE_INIT; } /*****************************************************************************/ @@ -554,7 +476,7 @@ deactivate(NMDevice *device) static void modem_deactivate_async_cb(NMModem *modem, GError *error, gpointer user_data) { - gs_unref_object NMDevice * self = NULL; + gs_unref_object NMDevice *self = NULL; NMDeviceDeactivateCallback callback; gpointer callback_user_data; @@ -563,8 +485,8 @@ modem_deactivate_async_cb(NMModem *modem, GError *error, gpointer user_data) } static void -deactivate_async(NMDevice * self, - GCancellable * cancellable, +deactivate_async(NMDevice *self, + GCancellable *cancellable, NMDeviceDeactivateCallback callback, gpointer user_data) { @@ -584,7 +506,7 @@ static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - NMActRequest * req; + NMActRequest *req; req = nm_device_get_act_request(device); g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); @@ -606,51 +528,44 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem); - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static NMActStageReturn -act_stage3_ip_config_start(NMDevice * device, - int addr_family, - gpointer * out_config, - NMDeviceStateReason *out_failure_reason) -{ - NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - gboolean autoip4 = FALSE; - NMActStageReturn ret; - - if (!NM_IS_IPv4(addr_family)) - return nm_modem_stage3_ip6_config_start(priv->modem, device, out_failure_reason); - - ret = nm_modem_stage3_ip4_config_start(priv->modem, device, &autoip4, out_failure_reason); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); - if (ret != NM_ACT_STAGE_RETURN_SUCCESS || !autoip4) - return ret; + if (priv->stage2_state == NM_DEVICE_STAGE_STATE_INIT) { + priv->stage2_state = NM_DEVICE_STAGE_STATE_PENDING; + return nm_modem_act_stage2_config(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, + device, + out_failure_reason); + } + if (priv->stage2_state == NM_DEVICE_STAGE_STATE_PENDING) + return NM_ACT_STAGE_RETURN_POSTPONE; - return NM_DEVICE_CLASS(nm_device_modem_parent_class) - ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason); + nm_assert(priv->stage2_state == NM_DEVICE_STAGE_STATE_COMPLETED); + return NM_ACT_STAGE_RETURN_SUCCESS; } static void -ip4_config_pre_commit(NMDevice *device, NMIP4Config *config) +act_stage3_ip_config(NMDevice *device, int addr_family) { - nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device, config); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device); + + if (nm_modem_stage3_ip_config_start(priv->modem, addr_family, device)) + nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_PENDING, NULL); } static gboolean get_ip_iface_identifier(NMDevice *device, NMUtilsIPv6IfaceId *out_iid) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); - gboolean success; g_return_val_if_fail(priv->modem, FALSE); - success = nm_modem_get_iid(priv->modem, out_iid); - if (!success) - success = - NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid); - return success; + + if (priv->iid.id != 0) { + *out_iid = priv->iid; + return TRUE; + } + + return NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid); } /*****************************************************************************/ @@ -667,7 +582,7 @@ get_enabled(NMDevice *device) static void set_enabled(NMDevice *device, gboolean enabled) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); /* Called only by the Manager in response to rfkill switch changes or @@ -688,7 +603,7 @@ set_enabled(NMDevice *device, gboolean enabled) static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - NMDeviceModem * self = NM_DEVICE_MODEM(device); + NMDeviceModem *self = NM_DEVICE_MODEM(device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self); NMModemState modem_state; @@ -703,6 +618,16 @@ is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) return TRUE; } +static gboolean +ready_for_ip_config(NMDevice *device) +{ + /* Tell NMDevice to only run device-specific IP + * configuration (devip) and skip other methods + * (manual, dhcp, etc). + */ + return FALSE; +} + /*****************************************************************************/ static void @@ -716,8 +641,7 @@ set_modem(NMDeviceModem *self, NMModem *modem) g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self); g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self); - g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self); - g_signal_connect(modem, NM_MODEM_IP6_CONFIG_RESULT, G_CALLBACK(modem_ip6_config_result), self); + g_signal_connect(modem, NM_MODEM_NEW_CONFIG, G_CALLBACK(modem_new_config), self); g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self); g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self); g_signal_connect(modem, NM_MODEM_STATE_CHANGED, G_CALLBACK(modem_state_cb), self); @@ -838,9 +762,9 @@ nm_device_modem_new(NMModem *modem) NM_DEVICE_MODEM_MODEM, modem, NM_DEVICE_MODEM_CAPABILITIES, - caps, + (guint) ((guint32) caps), NM_DEVICE_MODEM_CURRENT_CAPABILITIES, - current_caps, + (guint) ((guint32) current_caps), NM_DEVICE_MODEM_DEVICE_ID, nm_modem_get_device_id(modem), NULL); @@ -885,9 +809,9 @@ static const NMDBusInterfaceInfoExtended interface_info_device_modem = { static void nm_device_modem_class_init(NMDeviceModemClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); - NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->dispose = dispose; object_class->get_property = get_property; @@ -904,8 +828,7 @@ nm_device_modem_class_init(NMDeviceModemClass *klass) device_class->deactivate = deactivate; device_class->act_stage1_prepare = act_stage1_prepare; device_class->act_stage2_config = act_stage2_config; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->ip4_config_pre_commit = ip4_config_pre_commit; + device_class->act_stage3_ip_config = act_stage3_ip_config; device_class->get_enabled = get_enabled; device_class->set_enabled = set_enabled; device_class->owns_iface = owns_iface; @@ -913,6 +836,7 @@ nm_device_modem_class_init(NMDeviceModemClass *klass) device_class->get_ip_iface_identifier = get_ip_iface_identifier; device_class->get_configured_mtu = nm_modem_get_configured_mtu; device_class->get_dhcp_timeout_for_device = get_dhcp_timeout_for_device; + device_class->ready_for_ip_config = ready_for_ip_config; device_class->state_changed = device_state_changed; diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index a5139f08..f5336d37 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -16,29 +16,20 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" #include "libnm-platform/nm-platform.h" -#include "nm-ip4-config.h" -#include "nm-ip6-config.h" +#include "nm-l3-config-data.h" #define NM_MODEM_BROADBAND_MODEM "modem" -static gboolean -MODEM_CAPS_3GPP(MMModemCapability caps) -{ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - /* MM_MODEM_CAPABILITY_LTE_ADVANCED is marked as deprecated since ModemManager 1.14.0. - * - * The flag probably was never used, it certainly isn't used since 1.14.0. - * - * Still, just to be sure, there is no harm in checking it here. Suppress the - * warning, it should have no bad effect. - */ - return NM_FLAGS_ANY(caps, - (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE - | MM_MODEM_CAPABILITY_LTE_ADVANCED)); - G_GNUC_END_IGNORE_DEPRECATIONS -} +#if !MM_CHECK_VERSION(1, 14, 0) +#define MM_MODEM_CAPABILITY_5GNR ((MMModemCapability) (1 << 6)) +#endif + +#define MODEM_CAPS_3GPP(caps) \ + NM_FLAGS_ANY( \ + caps, \ + (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR)) -#define MODEM_CAPS_3GPP2(caps) (caps & (MM_MODEM_CAPABILITY_CDMA_EVDO)) +#define MODEM_CAPS_3GPP2(caps) NM_FLAGS_ANY((caps), MM_MODEM_CAPABILITY_CDMA_EVDO) /* Maximum time to keep the DBus call waiting for a connection result. * This value is greater than the default timeout in ModemManager (180s since @@ -62,13 +53,13 @@ typedef struct { ConnectStep step; MMModemCapability caps; - NMConnection * connection; - GCancellable * cancellable; + NMConnection *connection; + GCancellable *cancellable; MMSimpleConnectProperties *connect_properties; - GArray * ip_types; + GArray *ip_types; guint ip_types_i; guint ip_type_tries; - GError * first_error; + GError *first_error; } ConnectContext; /*****************************************************************************/ @@ -79,21 +70,18 @@ typedef struct { /* The modem object from dbus */ MMObject *modem_object; /* Per-interface objects */ - MMModem * modem_iface; - MMModem3gpp * modem_3gpp_iface; + MMModem *modem_iface; + MMModem3gpp *modem_3gpp_iface; MMModemSimple *simple_iface; - MMSim * sim_iface; + MMSim *sim_iface; /* Connection setup */ ConnectContext *ctx; - MMBearer * bearer; + MMBearer *bearer; MMBearerIpConfig *ipv4_config; MMBearerIpConfig *ipv6_config; - guint idle_id_ip4; - guint idle_id_ip6; - guint32 pin_tries; } NMModemBroadbandPrivate; @@ -123,7 +111,7 @@ G_DEFINE_TYPE(NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM) if (nm_logging_enabled(_level, (_NMLOG_DOMAIN))) { \ NMModemBroadband *const __self = (self); \ char __prefix_name[128]; \ - const char * __uid; \ + const char *__uid; \ \ _nm_log(_level, \ (_NMLOG_DOMAIN), \ @@ -199,24 +187,28 @@ translate_mm_error(NMModemBroadband *self, GError *error) /*****************************************************************************/ static void -get_capabilities(NMModem * _self, +get_capabilities(NMModem *_self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps) { - NMModemBroadband * self = NM_MODEM_BROADBAND(_self); - MMModemCapability all_supported = MM_MODEM_CAPABILITY_NONE; - MMModemCapability *supported; - guint n_supported; + NMModemBroadband *self = NM_MODEM_BROADBAND(_self); + MMModemCapability all_supported = MM_MODEM_CAPABILITY_NONE; + gs_free MMModemCapability *supported = NULL; + guint n_supported; + guint i; + + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_POTS == (guint64) NM_DEVICE_MODEM_CAPABILITY_POTS); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_CDMA_EVDO + == (guint64) NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_GSM_UMTS == (guint64) NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_LTE == (guint64) NM_DEVICE_MODEM_CAPABILITY_LTE); + G_STATIC_ASSERT(MM_MODEM_CAPABILITY_5GNR == (guint64) NM_DEVICE_MODEM_CAPABILITY_5GNR); /* For now, we don't care about the capability combinations, just merge all * combinations in a single mask */ if (mm_modem_get_supported_capabilities(self->_priv.modem_iface, &supported, &n_supported)) { - guint i; - for (i = 0; i < n_supported; i++) all_supported |= supported[i]; - - g_free(supported); } *modem_caps = (NMDeviceModemCapabilities) all_supported; @@ -227,7 +219,7 @@ get_capabilities(NMModem * _self, static gboolean owns_port(NMModem *_self, const char *iface) { - NMModemBroadband * self = NM_MODEM_BROADBAND(_self); + NMModemBroadband *self = NM_MODEM_BROADBAND(_self); const MMModemPortInfo *ports = NULL; guint n_ports = 0, i; @@ -278,7 +270,7 @@ create_cdma_connect_properties(NMConnection *connection) #if !MM_CHECK_VERSION(1, 9, 1) { NMSettingCdma *setting; - const char * str; + const char *str; setting = nm_connection_get_setting_cdma(connection); str = nm_setting_cdma_get_number(setting); @@ -292,14 +284,14 @@ create_cdma_connect_properties(NMConnection *connection) static MMSimpleConnectProperties * create_gsm_connect_properties(NMConnection *connection, - const char * apn, - const char * username, - const char * password) + const char *apn, + const char *username, + const char *password) { - NMSettingGsm * setting; - NMSettingPpp * s_ppp; + NMSettingGsm *setting; + NMSettingPpp *s_ppp; MMSimpleConnectProperties *properties; - const char * str; + const char *str; setting = nm_connection_get_setting_gsm(connection); @@ -369,11 +361,11 @@ static void connect_context_step(NMModemBroadband *self); static void connect_ready(MMModemSimple *simple_iface, GAsyncResult *res, NMModemBroadband *self) { - ConnectContext *ctx; - GError * error = NULL; - NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; - NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - gs_unref_object MMBearer *bearer = NULL; + ConnectContext *ctx; + GError *error = NULL; + NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; + NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; + gs_unref_object MMBearer *bearer = NULL; bearer = mm_modem_simple_connect_finish(simple_iface, res, &error); @@ -480,18 +472,18 @@ send_pin_ready(MMSim *sim, GAsyncResult *result, NMModemBroadband *self) } static void -find_gsm_apn_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +find_gsm_apn_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { - NMModemBroadband * self = user_data; + NMModemBroadband *self = user_data; NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - ConnectContext * ctx = priv->ctx; + ConnectContext *ctx = priv->ctx; if (error) { _LOGW("failed to connect '%s': APN not found: %s", @@ -514,14 +506,14 @@ static gboolean try_create_connect_properties(NMModemBroadband *self) { NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - ConnectContext * ctx = priv->ctx; + ConnectContext *ctx = priv->ctx; if (MODEM_CAPS_3GPP(ctx->caps)) { NMSettingGsm *s_gsm = nm_connection_get_setting_gsm(ctx->connection); if (!s_gsm || nm_setting_gsm_get_auto_config(s_gsm)) { gs_unref_object MMModem3gpp *modem_3gpp = NULL; - const char * network_id = NULL; + const char *network_id = NULL; s_gsm = nm_connection_get_setting_gsm(ctx->connection); if (s_gsm) @@ -590,7 +582,7 @@ connect_context_step(NMModemBroadband *self) if (MODEM_CAPS_3GPP(ctx->caps) && mm_modem_get_unlock_required(self->_priv.modem_iface) == MM_MODEM_LOCK_SIM_PIN) { NMSettingGsm *s_gsm = nm_connection_get_setting_gsm(ctx->connection); - const char * pin = nm_setting_gsm_get_pin(s_gsm); + const char *pin = nm_setting_gsm_get_pin(s_gsm); /* If we have a PIN already, send it. If we don't, get it. */ if (pin) { @@ -698,8 +690,8 @@ connect_context_step(NMModemBroadband *self) } static NMActStageReturn -modem_act_stage1_prepare(NMModem * _self, - NMConnection * connection, +modem_act_stage1_prepare(NMModem *_self, + NMConnection *connection, NMDeviceStateReason *out_failure_reason) { NMModemBroadband *self = NM_MODEM_BROADBAND(_self); @@ -772,15 +764,15 @@ check_connection_compatible_with_modem(NMModem *_self, NMConnection *connection, /*****************************************************************************/ static gboolean -complete_connection(NMModem * modem, - const char * iface, - NMConnection * connection, +complete_connection(NMModem *modem, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMModemBroadband *self = NM_MODEM_BROADBAND(modem); MMModemCapability modem_caps; - NMSettingPpp * s_ppp; + NMSettingPpp *s_ppp; modem_caps = mm_modem_get_current_capabilities(self->_priv.modem_iface); @@ -860,7 +852,7 @@ complete_connection(NMModem * modem, static gboolean get_user_pass(NMModem *modem, NMConnection *connection, const char **user, const char **pass) { - NMSettingGsm * s_gsm; + NMSettingGsm *s_gsm; NMSettingCdma *s_cdma; s_gsm = nm_connection_get_setting_gsm(connection); @@ -958,259 +950,257 @@ set_mm_enabled(NMModem *_self, gboolean enabled) } /*****************************************************************************/ -/* IPv4 method static */ -static gboolean -static_stage3_ip4_done(NMModemBroadband *self) +static void +stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_method) { - GError * error = NULL; - gs_unref_object NMIP4Config *config = NULL; - const char * data_port; - const char * address_string; - const char * gw_string; - guint32 address_network; - guint32 gw = 0; - NMPlatformIP4Address address; - const char ** dns; - guint i; - guint32 ip4_route_table, ip4_route_metric; - NMPlatformIP4Route * r; - guint32 mtu_n; - - g_return_val_if_fail(self->_priv.ipv4_config, FALSE); - g_return_val_if_fail(self->_priv.bearer, FALSE); - - self->_priv.idle_id_ip4 = 0; - - _LOGI("IPv4 static configuration:"); - - /* Fully fail if invalid IP address retrieved */ - address_string = mm_bearer_ip_config_get_address(self->_priv.ipv4_config); - if (!address_string - || !nm_utils_parse_inaddr_bin(AF_INET, address_string, NULL, &address_network)) { - error = - g_error_new(NM_DEVICE_ERROR, + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMModemBroadband *self = NM_MODEM_BROADBAND(modem); + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + gs_free_error GError *error = NULL; + const char *data_port; + const char *address_string; + const char **dns; + guint i; + gboolean do_auto = FALSE; + int ifindex; + NMUtilsIPv6IfaceId iid_data; + const NMUtilsIPv6IfaceId *iid = NULL; + + if (IS_IPv4) { + g_return_if_fail(self->_priv.ipv4_config); + g_return_if_fail(self->_priv.bearer); + + if (ip_method == NM_MODEM_IP_METHOD_AUTO) { + do_auto = TRUE; + goto out; + } + } else { + g_return_if_fail(self->_priv.ipv6_config); + } + + if (IS_IPv4) { + guint32 address_network; + guint32 gw = 0; + NMPlatformIP4Address address; + NMPlatformIP4Route route; + guint32 mtu_n; + const char *gw_string; + + _LOGI("IPv4 static configuration:"); + + /* Fully fail if invalid IP address retrieved */ + address_string = mm_bearer_ip_config_get_address(self->_priv.ipv4_config); + if (!address_string + || !nm_utils_parse_inaddr_bin(AF_INET, address_string, NULL, &address_network)) { + g_set_error(&error, + NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s", nm_modem_get_uid(NM_MODEM(self)), NM_PRINT_FMT_QUOTE_STRING(address_string)); - goto out; - } + goto out; + } - /* Missing gateway not a hard failure */ - gw_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv4_config); - if (gw_string && !nm_utils_parse_inaddr_bin(AF_INET, gw_string, NULL, &gw)) { - error = - g_error_new(NM_DEVICE_ERROR, + /* Missing gateway not a hard failure */ + gw_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv4_config); + if (gw_string && !nm_utils_parse_inaddr_bin(AF_INET, gw_string, NULL, &gw)) { + g_set_error(&error, + NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"", nm_modem_get_uid(NM_MODEM(self)), gw_string); - goto out; - } - - data_port = mm_bearer_get_interface(self->_priv.bearer); - g_return_val_if_fail(data_port, FALSE); - config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), - nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port)); - - memset(&address, 0, sizeof(address)); - address.address = address_network; - address.peer_address = address_network; - address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config); - address.addr_source = NM_IP_CONFIG_SOURCE_WWAN; - if (address.plen <= 32) - nm_ip4_config_add_address(config, &address); - - _LOGI(" address %s/%d", address_string, address.plen); - - nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL); - r = &(NMPlatformIP4Route){ - .rt_source = NM_IP_CONFIG_SOURCE_WWAN, - .gateway = gw, - .table_coerced = nm_platform_route_table_coerce(ip4_route_table), - .metric = ip4_route_metric, - }; - nm_ip4_config_add_route(config, r, NULL); - _LOGI(" gateway %s", gw_string); - - /* DNS servers */ - dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config); - for (i = 0; dns && dns[i]; i++) { - if (nm_utils_parse_inaddr_bin(AF_INET, dns[i], NULL, &address_network) - && address_network > 0) { - nm_ip4_config_add_nameserver(config, address_network); - _LOGI(" DNS %s", dns[i]); + goto out; } - } -#if MM_CHECK_VERSION(1, 4, 0) - mtu_n = mm_bearer_ip_config_get_mtu(self->_priv.ipv4_config); - if (mtu_n) { - nm_ip4_config_set_mtu(config, mtu_n, NM_IP_CONFIG_SOURCE_WWAN); - _LOGI(" MTU %u", mtu_n); - } -#endif - -out: - g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, config, error); - g_clear_error(&error); - return FALSE; -} + data_port = mm_bearer_get_interface(self->_priv.bearer); + g_return_if_fail(data_port); -static NMActStageReturn -static_stage3_ip4_config_start(NMModem * modem, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason) -{ - NMModemBroadband * self = NM_MODEM_BROADBAND(modem); - NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port); + if (ifindex <= 0) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) data port %s not found", + nm_modem_get_uid(NM_MODEM(self)), + data_port); + goto out; + } - /* We schedule it in an idle just to follow the same logic as in the - * generic modem implementation. */ - nm_clear_g_source(&priv->idle_id_ip4); - priv->idle_id_ip4 = g_idle_add((GSourceFunc) static_stage3_ip4_done, self); + l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), + ifindex, + NM_IP_CONFIG_SOURCE_WWAN); + + address = (NMPlatformIP4Address){ + .address = address_network, + .peer_address = address_network, + .plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config), + .addr_source = NM_IP_CONFIG_SOURCE_WWAN, + }; + if (address.plen <= 32) + nm_l3_config_data_add_address_4(l3cd, &address); + + _LOGI(" address %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf))); + + route = (NMPlatformIP4Route){ + .rt_source = NM_IP_CONFIG_SOURCE_WWAN, + .gateway = gw, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, + }; + nm_l3_config_data_add_route_4(l3cd, &route); + _LOGI(" gateway %s", gw_string); + + dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config); + for (i = 0; dns && dns[i]; i++) { + if (nm_utils_parse_inaddr_bin(AF_INET, dns[i], NULL, &address_network) + && address_network > 0) { + nm_l3_config_data_add_nameserver(l3cd, AF_INET, &address_network); + _LOGI(" DNS %s", dns[i]); + } + } - return NM_ACT_STAGE_RETURN_POSTPONE; -} +#if MM_CHECK_VERSION(1, 4, 0) + mtu_n = mm_bearer_ip_config_get_mtu(self->_priv.ipv4_config); + if (mtu_n) { + nm_l3_config_data_set_mtu(l3cd, mtu_n); + _LOGI(" MTU %u", mtu_n); + } +#endif + } else { + NMPlatformIP6Address address; + + address_string = mm_bearer_ip_config_get_address(self->_priv.ipv6_config); + if (!address_string) { + /* DHCP/SLAAC is allowed to skip addresses; other methods require it */ + if (ip_method != NM_MODEM_IP_METHOD_AUTO) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) retrieving IPv6 configuration failed: no address given", + nm_modem_get_uid(NM_MODEM(self))); + } + goto out; + } -/*****************************************************************************/ -/* IPv6 method static */ + address = (NMPlatformIP6Address){}; -static gboolean -stage3_ip6_done(NMModemBroadband *self) -{ - GError * error = NULL; - NMIP6Config * config = NULL; - const char * data_port; - const char * address_string; - NMPlatformIP6Address address; - NMModemIPMethod ip_method; - const char ** dns; - guint i; - - g_return_val_if_fail(self->_priv.ipv6_config, FALSE); - - self->_priv.idle_id_ip6 = 0; - memset(&address, 0, sizeof(address)); - - ip_method = get_bearer_ip_method(self->_priv.ipv6_config); - - address_string = mm_bearer_ip_config_get_address(self->_priv.ipv6_config); - if (!address_string) { - /* DHCP/SLAAC is allowed to skip addresses; other methods require it */ - if (ip_method != NM_MODEM_IP_METHOD_AUTO) { - error = g_error_new(NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IPv6 configuration failed: no address given", - nm_modem_get_uid(NM_MODEM(self))); + if (!inet_pton(AF_INET6, address_string, &address.address)) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) retrieving IPv6 configuration failed: invalid address given '%s'", + nm_modem_get_uid(NM_MODEM(self)), + address_string); + goto out; } - goto out; - } - /* Fail if invalid IP address retrieved */ - if (!inet_pton(AF_INET6, address_string, (void *) &(address.address))) { - error = g_error_new(NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IPv6 configuration failed: invalid address given '%s'", - nm_modem_get_uid(NM_MODEM(self)), - address_string); - goto out; - } + data_port = mm_bearer_get_interface(self->_priv.bearer); + g_return_if_fail(data_port); - _LOGI("IPv6 base configuration:"); + ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port); + if (ifindex <= 0) { + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) data port %s not found", + nm_modem_get_uid(NM_MODEM(self)), + data_port); + goto out; + } - data_port = mm_bearer_get_interface(self->_priv.bearer); - g_return_val_if_fail(data_port, FALSE); + _LOGI("IPv6 base configuration:"); - config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), - nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port)); + l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), + ifindex, + NM_IP_CONFIG_SOURCE_WWAN); - address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config); - if (address.plen <= 128) - nm_ip6_config_add_address(config, &address); + do_auto = TRUE; - _LOGI(" address %s/%d", address_string, address.plen); + address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config); + if (address.plen <= 128) { + if (IN6_IS_ADDR_LINKLOCAL(&address.address)) { + iid_data.id = ((guint64 *) (&address.address.s6_addr))[1]; + iid = &iid_data; + } else + do_auto = FALSE; + nm_l3_config_data_add_address_6(l3cd, &address); + } - address_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv6_config); - if (address_string) { - guint32 ip6_route_table, ip6_route_metric; + _LOGI(" address %s (slaac %s)", + nm_platform_ip6_address_to_string(&address, sbuf, sizeof(sbuf)), + do_auto ? "enabled" : "disabled"); - if (inet_pton(AF_INET6, address_string, &address.address) != 1) { - error = - g_error_new(NM_DEVICE_ERROR, + address_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv6_config); + if (address_string) { + if (inet_pton(AF_INET6, address_string, &address.address) != 1) { + g_set_error(&error, + NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'", nm_modem_get_uid(NM_MODEM(self)), address_string); - goto out; - } + goto out; + } - nm_modem_get_route_parameters(NM_MODEM(self), - NULL, - NULL, - &ip6_route_table, - &ip6_route_metric); - { - const NMPlatformIP6Route r = { - .rt_source = NM_IP_CONFIG_SOURCE_WWAN, - .gateway = address.address, - .table_coerced = nm_platform_route_table_coerce(ip6_route_table), - .metric = ip6_route_metric, - }; - - _LOGI(" gateway %s", address_string); - nm_ip6_config_add_route(config, &r, NULL); + { + const NMPlatformIP6Route r = { + .rt_source = NM_IP_CONFIG_SOURCE_WWAN, + .gateway = address.address, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, + }; + + _LOGI(" gateway %s", address_string); + nm_l3_config_data_add_route_6(l3cd, &r); + } + } else if (ip_method == NM_MODEM_IP_METHOD_STATIC) { + /* Gateway required for the 'static' method */ + g_set_error(&error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "(%s) retrieving IPv6 configuration failed: missing gateway", + nm_modem_get_uid(NM_MODEM(self))); + goto out; } - } else if (ip_method == NM_MODEM_IP_METHOD_STATIC) { - /* Gateway required for the 'static' method */ - error = g_error_new(NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "(%s) retrieving IPv6 configuration failed: missing gateway", - nm_modem_get_uid(NM_MODEM(self))); - goto out; - } - /* DNS servers */ - dns = mm_bearer_ip_config_get_dns(self->_priv.ipv6_config); - for (i = 0; dns && dns[i]; i++) { - struct in6_addr addr; + dns = mm_bearer_ip_config_get_dns(self->_priv.ipv6_config); + for (i = 0; dns && dns[i]; i++) { + struct in6_addr addr; - if (inet_pton(AF_INET6, dns[i], &addr)) { - nm_ip6_config_add_nameserver(config, &addr); - _LOGI(" DNS %s", dns[i]); + if (inet_pton(AF_INET6, dns[i], &addr)) { + nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &addr); + _LOGI(" DNS %s", dns[i]); + } } } out: - nm_modem_emit_ip6_config_result(NM_MODEM(self), config, error); - g_clear_object(&config); - g_clear_error(&error); - return FALSE; -} - -static NMActStageReturn -stage3_ip6_config_request(NMModem *modem, NMDeviceStateReason *out_failure_reason) -{ - NMModemBroadband * self = NM_MODEM_BROADBAND(modem); - NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - - /* We schedule it in an idle just to follow the same logic as in the - * generic modem implementation. */ - nm_clear_g_source(&priv->idle_id_ip6); - priv->idle_id_ip6 = g_idle_add((GSourceFunc) stage3_ip6_done, self); + if (error) { + nm_modem_emit_signal_new_config_failure(modem, + addr_family, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, + error); + return; + } - return NM_ACT_STAGE_RETURN_POSTPONE; + nm_modem_emit_signal_new_config_success(modem, addr_family, l3cd, do_auto, iid); } /*****************************************************************************/ /* Disconnect */ typedef struct { - NMModemBroadband * self; + NMModemBroadband *self; _NMModemDisconnectCallback callback; gpointer callback_user_data; - GCancellable * cancellable; + GCancellable *cancellable; gboolean warn; } DisconnectContext; @@ -1227,7 +1217,7 @@ disconnect_context_complete(DisconnectContext *ctx, GError *error) static void disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellable) { - DisconnectContext *ctx = user_data; + DisconnectContext *ctx = user_data; gs_free_error GError *cancelled_error = NULL; g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error); @@ -1237,9 +1227,9 @@ disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellabl static void simple_disconnect_ready(GObject *source_object, GAsyncResult *res, gpointer user_data) { - MMModemSimple * modem_iface = MM_MODEM_SIMPLE(source_object); - DisconnectContext *ctx = user_data; - gs_free_error GError *error = NULL; + MMModemSimple *modem_iface = MM_MODEM_SIMPLE(source_object); + DisconnectContext *ctx = user_data; + gs_free_error GError *error = NULL; if (!mm_modem_simple_disconnect_finish(modem_iface, res, &error)) { if (ctx->warn && !g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { @@ -1253,13 +1243,13 @@ simple_disconnect_ready(GObject *source_object, GAsyncResult *res, gpointer user } static void -disconnect(NMModem * modem, +disconnect(NMModem *modem, gboolean warn, - GCancellable * cancellable, + GCancellable *cancellable, _NMModemDisconnectCallback callback, gpointer user_data) { - NMModemBroadband * self = NM_MODEM_BROADBAND(modem); + NMModemBroadband *self = NM_MODEM_BROADBAND(modem); DisconnectContext *ctx; connect_context_clear(self); @@ -1336,11 +1326,11 @@ mm_state_to_nm(MMModemState mm_state) } static void -modem_state_changed(MMModem * modem, +modem_state_changed(MMModem *modem, MMModemState old_state, MMModemState new_state, MMModemStateChangeReason reason, - NMModemBroadband * self) + NMModemBroadband *self) { /* After the SIM is unlocked MM1 will move the device to INITIALIZING which * is an unavailable state. That makes state handling confusing here, so @@ -1378,7 +1368,7 @@ static void get_sim_ready(MMModem *modem, GAsyncResult *res, NMModemBroadband *self) { GError *error = NULL; - MMSim * new_sim; + MMSim *new_sim; new_sim = mm_modem_get_sim_finish(modem, res, &error); if (new_sim != self->_priv.sim_iface) { @@ -1512,12 +1502,12 @@ nm_modem_broadband_init(NMModemBroadband *self) NMModem * nm_modem_broadband_new(GObject *object, GError **error) { - MMObject * modem_object; - MMModem * modem_iface; - MMModem3gpp * modem_3gpp_iface; + MMObject *modem_object; + MMModem *modem_iface; + MMModem3gpp *modem_3gpp_iface; const char *const *drivers; - const char * operator_code = NULL; - gs_free char * driver = NULL; + const char *operator_code = NULL; + gs_free char *driver = NULL; g_return_val_if_fail(MM_IS_OBJECT(object), NULL); modem_object = MM_OBJECT(object); @@ -1561,30 +1551,27 @@ nm_modem_broadband_new(GObject *object, GError **error) static void dispose(GObject *object) { - NMModemBroadband * self = NM_MODEM_BROADBAND(object); + NMModemBroadband *self = NM_MODEM_BROADBAND(object); NMModemBroadbandPrivate *priv = NM_MODEM_BROADBAND_GET_PRIVATE(self); - nm_clear_g_source(&priv->idle_id_ip4); - nm_clear_g_source(&priv->idle_id_ip6); - connect_context_clear(self); - g_clear_object(&self->_priv.ipv4_config); - g_clear_object(&self->_priv.ipv6_config); - g_clear_object(&self->_priv.bearer); + g_clear_object(&priv->ipv4_config); + g_clear_object(&priv->ipv6_config); + g_clear_object(&priv->bearer); - if (self->_priv.modem_iface) { - g_signal_handlers_disconnect_by_data(self->_priv.modem_iface, self); - g_clear_object(&self->_priv.modem_iface); + if (priv->modem_iface) { + g_signal_handlers_disconnect_by_data(priv->modem_iface, self); + g_clear_object(&priv->modem_iface); } - if (self->_priv.modem_3gpp_iface) { - g_signal_handlers_disconnect_by_data(self->_priv.modem_3gpp_iface, self); - g_clear_object(&self->_priv.modem_3gpp_iface); + if (priv->modem_3gpp_iface) { + g_signal_handlers_disconnect_by_data(priv->modem_3gpp_iface, self); + g_clear_object(&priv->modem_3gpp_iface); } - g_clear_object(&self->_priv.simple_iface); - g_clear_object(&self->_priv.sim_iface); - g_clear_object(&self->_priv.modem_object); + g_clear_object(&priv->simple_iface); + g_clear_object(&priv->sim_iface); + g_clear_object(&priv->modem_object); G_OBJECT_CLASS(nm_modem_broadband_parent_class)->dispose(object); } @@ -1600,8 +1587,7 @@ nm_modem_broadband_class_init(NMModemBroadbandClass *klass) object_class->set_property = set_property; modem_class->get_capabilities = get_capabilities; - modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; - modem_class->stage3_ip6_config_request = stage3_ip6_config_request; + modem_class->stage3_ip_config_start = stage3_ip_config_start; modem_class->disconnect = disconnect; modem_class->deactivate_cleanup = deactivate_cleanup; modem_class->set_mm_enabled = set_mm_enabled; diff --git a/src/core/devices/wwan/nm-modem-manager.c b/src/core/devices/wwan/nm-modem-manager.c index 8d087d13..4a89f38e 100644 --- a/src/core/devices/wwan/nm-modem-manager.c +++ b/src/core/devices/wwan/nm-modem-manager.c @@ -45,7 +45,7 @@ typedef struct { GCancellable *main_cancellable; struct { - MMManager * manager; + MMManager *manager; GCancellable *poke_cancellable; gulong handle_name_owner_changed_id; gulong handle_object_added_id; @@ -61,15 +61,15 @@ typedef struct { LOG_AVAILABLE_NO, } log_available : 3; - GDBusProxy * proxy; + GDBusProxy *proxy; GCancellable *proxy_cancellable; guint proxy_ref_count; - char * proxy_name_owner; + char *proxy_name_owner; } modm; #if WITH_OFONO struct { - GDBusProxy * proxy; + GDBusProxy *proxy; GCancellable *cancellable; } ofono; #endif @@ -111,7 +111,7 @@ static void handle_new_modem(NMModemManager *self, NMModem *modem) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - const char * path; + const char *path; path = nm_modem_get_path(modem); if (g_hash_table_lookup(priv->modems, path)) { @@ -163,10 +163,10 @@ static void modm_handle_object_added(MMManager *modem_manager, MMObject *modem_object, NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - const char * path; - MMModem * modem_iface; - NMModem * modem; - GError * error = NULL; + const char *path; + MMModem *modem_iface; + NMModem *modem; + GError *error = NULL; /* Ensure we don't have the same modem already */ path = mm_object_get_path(modem_object); @@ -201,8 +201,8 @@ static void modm_handle_object_removed(MMManager *manager, MMObject *modem_object, NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - NMModem * modem; - const char * path; + NMModem *modem; + const char *path; path = mm_object_get_path(modem_object); modem = (NMModem *) g_hash_table_lookup(priv->modems, path); @@ -217,7 +217,7 @@ static void modm_manager_available(NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - GList * modems, *l; + GList *modems, *l; if (priv->modm.log_available != LOG_AVAILABLE_YES) { _LOGI("ModemManager %savailable", priv->modm.log_available ? "now " : ""); @@ -235,7 +235,7 @@ static void modm_handle_name_owner_changed(MMManager *modem_manager, GParamSpec *pspec, NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - char * name_owner; + char *name_owner; /* Quit poking, if any */ nm_clear_g_source(&priv->modm.relaunch_id); @@ -273,9 +273,9 @@ modm_handle_name_owner_changed(MMManager *modem_manager, GParamSpec *pspec, NMMo static void modm_manager_poke_cb(GObject *connection, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; - NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; + NMModemManager *self; + NMModemManagerPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *result = NULL; result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(connection), res, &error); @@ -327,7 +327,7 @@ static void modm_manager_check_name_owner(NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - gs_free char * name_owner = NULL; + gs_free char *name_owner = NULL; name_owner = g_dbus_object_manager_client_get_name_owner( G_DBUS_OBJECT_MANAGER_CLIENT(priv->modm.manager)); @@ -344,10 +344,10 @@ modm_manager_check_name_owner(NMModemManager *self) static void modm_manager_new_cb(GObject *source, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - MMManager * modem_manager; + gs_free_error GError *error = NULL; + MMManager *modem_manager; modem_manager = mm_manager_new_finish(res, &error); if (!modem_manager && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -445,7 +445,7 @@ static void modm_proxy_name_owner_reset(NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - char * name = NULL; + char *name = NULL; if (priv->modm.proxy) name = g_dbus_proxy_get_name_owner(priv->modm.proxy); @@ -469,10 +469,10 @@ modm_proxy_name_owner_changed_cb(GObject *object, GParamSpec *pspec, gpointer us static void modm_proxy_new_cb(GObject *source_object, GAsyncResult *result, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - GDBusProxy * proxy; - gs_free_error GError *error = NULL; + GDBusProxy *proxy; + gs_free_error GError *error = NULL; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -567,7 +567,7 @@ static void ofono_create_modem(NMModemManager *self, const char *path) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - NMModem * modem = NULL; + NMModem *modem = NULL; /* Ensure duplicate modems aren't created. Because we're not using the * ObjectManager interface there's a race during oFono startup where we @@ -585,15 +585,15 @@ ofono_create_modem(NMModemManager *self, const char *path) static void ofono_signal_cb(GDBusProxy *proxy, - char * sender_name, - char * signal_name, - GVariant * parameters, + char *sender_name, + char *signal_name, + GVariant *parameters, gpointer user_data) { - NMModemManager * self = NM_MODEM_MANAGER(user_data); + NMModemManager *self = NM_MODEM_MANAGER(user_data); NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - char * object_path; - NMModem * modem; + char *object_path; + NMModem *modem; if (g_strcmp0(signal_name, "ModemAdded") == 0) { g_variant_get(parameters, "(oa{sv})", &object_path, NULL); @@ -619,12 +619,12 @@ ofono_signal_cb(GDBusProxy *proxy, static void ofono_enumerate_devices_done(GObject *proxy, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - GVariant * results; - GVariantIter * iter; - const char * path; + gs_free_error GError *error = NULL; + GVariant *results; + GVariantIter *iter; + const char *path; results = g_dbus_proxy_call_finish(G_DBUS_PROXY(proxy), res, &error); if (!results && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -651,7 +651,7 @@ static void ofono_check_name_owner(NMModemManager *self, gboolean first_invocation) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); - gs_free char * name_owner = NULL; + gs_free char *name_owner = NULL; name_owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(priv->ofono.proxy)); if (name_owner) { @@ -670,7 +670,7 @@ ofono_check_name_owner(NMModemManager *self, gboolean first_invocation) self); } else { GHashTableIter iter; - NMModem * modem; + NMModem *modem; _LOGI("oFono is %savailable", first_invocation ? "not " : "no longer "); @@ -694,10 +694,10 @@ ofono_name_owner_changed(GDBusProxy *ofono_proxy, GParamSpec *pspec, NMModemMana static void ofono_proxy_new_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - GDBusProxy * proxy; + gs_free_error GError *error = NULL; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_finish(res, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -752,10 +752,10 @@ ofono_init_proxy(NMModemManager *self) static void bus_get_ready(GObject *source, GAsyncResult *res, gpointer user_data) { - NMModemManager * self; + NMModemManager *self; NMModemManagerPrivate *priv; - gs_free_error GError *error = NULL; - GDBusConnection * connection; + gs_free_error GError *error = NULL; + GDBusConnection *connection; connection = g_bus_get_finish(res, &error); if (!connection && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -782,7 +782,7 @@ bus_get_ready(GObject *source, GAsyncResult *res, gpointer user_data) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModemManager * self = NM_MODEM_MANAGER(object); + NMModemManager *self = NM_MODEM_MANAGER(object); NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); switch (prop_id) { @@ -812,7 +812,7 @@ nm_modem_manager_init(NMModemManager *self) static void dispose(GObject *object) { - NMModemManager * self = NM_MODEM_MANAGER(object); + NMModemManager *self = NM_MODEM_MANAGER(object); NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE(self); nm_clear_g_cancellable(&priv->main_cancellable); diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index 78ad7b68..cac90d32 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -11,7 +11,7 @@ #include "devices/nm-device-private.h" #include "nm-modem.h" #include "libnm-platform/nm-platform.h" -#include "nm-ip4-config.h" +#include "nm-l3-config-data.h" #define VARIANT_IS_OF_TYPE_BOOLEAN(v) \ ((v) != NULL && (g_variant_is_of_type((v), G_VARIANT_TYPE_BOOLEAN))) @@ -47,7 +47,7 @@ typedef struct { gboolean modem_online; gboolean gprs_attached; - NMIP4Config *ip4_config; + NML3ConfigData *l3cd_4; } NMModemOfonoPrivate; struct _NMModemOfono { @@ -75,7 +75,7 @@ G_DEFINE_TYPE(NMModemOfono, nm_modem_ofono, NM_TYPE_MODEM) if (nm_logging_enabled(_level, (_NMLOG_DOMAIN))) { \ NMModemOfono *const __self = (self); \ char __prefix_name[128]; \ - const char * __uid; \ + const char *__uid; \ \ _nm_log(_level, \ (_NMLOG_DOMAIN), \ @@ -97,7 +97,7 @@ G_DEFINE_TYPE(NMModemOfono, nm_modem_ofono, NM_TYPE_MODEM) /*****************************************************************************/ static void -get_capabilities(NMModem * _self, +get_capabilities(NMModem *_self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps) { @@ -112,7 +112,7 @@ update_modem_state(NMModemOfono *self) NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); NMModemState state = nm_modem_get_state(NM_MODEM(self)); NMModemState new_state = NM_MODEM_STATE_DISABLED; - const char * reason = NULL; + const char *reason = NULL; _LOGI("'Attached': %s 'Online': %s 'IMSI': %s", priv->gprs_attached ? "true" : "false", @@ -137,10 +137,10 @@ update_modem_state(NMModemOfono *self) /* Disconnect */ typedef struct { - NMModemOfono * self; + NMModemOfono *self; _NMModemDisconnectCallback callback; gpointer callback_user_data; - GCancellable * cancellable; + GCancellable *cancellable; gboolean warn; } DisconnectContext; @@ -157,7 +157,7 @@ disconnect_context_complete(DisconnectContext *ctx, GError *error) static void disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellable) { - DisconnectContext *ctx = user_data; + DisconnectContext *ctx = user_data; gs_free_error GError *error = NULL; if (!g_cancellable_set_error_if_cancelled(cancellable, &error)) { @@ -172,10 +172,10 @@ disconnect_context_complete_on_idle(gpointer user_data, GCancellable *cancellabl static void disconnect_done(GObject *source, GAsyncResult *result, gpointer user_data) { - DisconnectContext *ctx = user_data; - NMModemOfono * self = ctx->self; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *v = NULL; + DisconnectContext *ctx = user_data; + NMModemOfono *self = ctx->self; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *v = NULL; v = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { @@ -193,15 +193,15 @@ disconnect_done(GObject *source, GAsyncResult *result, gpointer user_data) } static void -disconnect(NMModem * modem, +disconnect(NMModem *modem, gboolean warn, - GCancellable * cancellable, + GCancellable *cancellable, _NMModemDisconnectCallback callback, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - DisconnectContext * ctx; + DisconnectContext *ctx; NMModemState state = nm_modem_get_state(NM_MODEM(self)); _LOGD("warn: %s modem_state: %s", warn ? "TRUE" : "FALSE", nm_modem_state_to_string(state)); @@ -235,12 +235,12 @@ disconnect(NMModem * modem, static void deactivate_cleanup(NMModem *modem, NMDevice *device, gboolean stop_ppp_manager) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); /* TODO: cancel SimpleConnect() if any */ - g_clear_object(&priv->ip4_config); + nm_clear_l3cd(&priv->l3cd_4); NM_MODEM_CLASS(nm_modem_ofono_parent_class) ->deactivate_cleanup(modem, device, stop_ppp_manager); @@ -249,9 +249,9 @@ deactivate_cleanup(NMModem *modem, NMDevice *device, gboolean stop_ppp_manager) static gboolean check_connection_compatible_with_modem(NMModem *modem, NMConnection *connection, GError **error) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - const char * id; + const char *id; if (!_nm_connection_check_main_setting(connection, NM_SETTING_GSM_SETTING_NAME, NULL)) { nm_utils_error_set(error, @@ -290,7 +290,7 @@ check_connection_compatible_with_modem(NMModem *modem, NMConnection *connection, static void handle_sim_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); if (g_strcmp0(property, "SubscriberIdentity") == 0 && VARIANT_IS_OF_TYPE_STRING(v)) { @@ -324,14 +324,14 @@ sim_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpoin static void sim_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; gs_unref_variant GVariant *v = NULL; GVariantIter i; - const char * property; + const char *property; v_properties = _nm_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, G_VARIANT_TYPE("(a{sv})"), &error); @@ -377,10 +377,10 @@ sim_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_dat static void _sim_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -451,7 +451,7 @@ handle_sim_iface(NMModemOfono *self, gboolean found) static void handle_connman_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); if (g_strcmp0(property, "Attached") == 0 && VARIANT_IS_OF_TYPE_BOOLEAN(v)) { @@ -483,14 +483,14 @@ connman_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, g static void connman_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; gs_unref_variant GVariant *v = NULL; GVariantIter i; - const char * property; + const char *property; v_properties = _nm_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, G_VARIANT_TYPE("(a{sv})"), &error); @@ -528,10 +528,10 @@ connman_get_properties_done(GObject *source, GAsyncResult *result, gpointer user static void _connman_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -606,7 +606,7 @@ handle_connman_iface(NMModemOfono *self, gboolean found) static void handle_modem_property(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); if ((g_strcmp0(property, "Online") == 0) && VARIANT_IS_OF_TYPE_BOOLEAN(v)) { @@ -655,14 +655,14 @@ modem_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpo static void modem_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *v_properties = NULL; gs_unref_variant GVariant *v_dict = NULL; - GVariant * v; + GVariant *v; GVariantIter i; - const char * property; + const char *property; v_properties = _nm_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, G_VARIANT_TYPE("(a{sv})"), &error); @@ -704,10 +704,10 @@ modem_get_properties_done(GObject *source, GAsyncResult *result, gpointer user_d static void stage1_prepare_done(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *v = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *v = NULL; v = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), result, &error); if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -732,17 +732,17 @@ stage1_prepare_done(GObject *source, GAsyncResult *result, gpointer user_data) static void handle_settings(GVariant *v_dict, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - NMPlatformIP4Address addr; + char sbuf[sizeof(_nm_utils_to_string_buffer)]; + NMPlatformIP4Address address; gboolean ret = FALSE; - const char * interface; - const char * s; - const char ** array, **iter; + const char *interface; + const char *s; + const char **array; guint32 address_network, gateway_network; - guint32 ip4_route_table, ip4_route_metric; int ifindex; - GError * error = NULL; + GError *error = NULL; //_LOGD("PropertyChanged: %s", property); @@ -773,12 +773,14 @@ handle_settings(GVariant *v_dict, gpointer user_data) } ifindex = nm_modem_get_ip_ifindex(NM_MODEM(self)); - nm_assert(ifindex > 0); + g_return_if_fail(ifindex > 0); - /* TODO: verify handling of ip4_config; check other places it's used... */ - g_clear_object(&priv->ip4_config); + /* TODO: verify handling of l3cd_4; check other places it's used... */ + nm_clear_l3cd(&priv->l3cd_4); - priv->ip4_config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), ifindex); + priv->l3cd_4 = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), + ifindex, + NM_IP_CONFIG_SOURCE_WWAN); if (!g_variant_lookup(v_dict, "Address", "&s", &s)) { _LOGW("Settings 'Address' missing"); @@ -788,10 +790,12 @@ handle_settings(GVariant *v_dict, gpointer user_data) _LOGW("can't convert 'Address' %s to addr", s ?: ""); goto out; } - memset(&addr, 0, sizeof(addr)); - addr.ifindex = ifindex; - addr.address = address_network; - addr.addr_source = NM_IP_CONFIG_SOURCE_WWAN; + + address = (NMPlatformIP4Address){ + .ifindex = ifindex, + .address = address_network, + .addr_source = NM_IP_CONFIG_SOURCE_WWAN, + }; if (!g_variant_lookup(v_dict, "Netmask", "&s", &s)) { _LOGW("Settings 'Netmask' missing"); @@ -801,10 +805,10 @@ handle_settings(GVariant *v_dict, gpointer user_data) _LOGW("invalid 'Netmask': %s", s ?: ""); goto out; } - addr.plen = nm_utils_ip4_netmask_to_prefix(address_network); + address.plen = nm_utils_ip4_netmask_to_prefix(address_network); - _LOGI("Address: %s", nm_platform_ip4_address_to_string(&addr, NULL, 0)); - nm_ip4_config_add_address(priv->ip4_config, &addr); + _LOGI("Address: %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf))); + nm_l3_config_data_add_address_4(priv->l3cd_4, &address); if (!g_variant_lookup(v_dict, "Gateway", "&s", &s) || !s) { _LOGW("Settings 'Gateway' missing"); @@ -814,17 +818,18 @@ handle_settings(GVariant *v_dict, gpointer user_data) _LOGW("invalid 'Gateway': %s", s); goto out; } - nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL); { const NMPlatformIP4Route r = { .rt_source = NM_IP_CONFIG_SOURCE_WWAN, .gateway = gateway_network, - .table_coerced = nm_platform_route_table_coerce(ip4_route_table), - .metric = ip4_route_metric, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, }; _LOGI("Gateway: %s", s); - nm_ip4_config_add_route(priv->ip4_config, &r, NULL); + nm_l3_config_data_add_route_4(priv->l3cd_4, &r); } if (!g_variant_lookup(v_dict, "DomainNameServers", "^a&s", &array)) { @@ -832,52 +837,48 @@ handle_settings(GVariant *v_dict, gpointer user_data) goto out; } if (array) { - for (iter = array; *iter; iter++) { - if (nm_utils_parse_inaddr_bin(AF_INET, *iter, NULL, &address_network) - && address_network) { - _LOGI("DNS: %s", *iter); - nm_ip4_config_add_nameserver(priv->ip4_config, address_network); - } else { - _LOGW("invalid NameServer: %s", *iter); + gboolean any_good = FALSE; + + for (; array[0]; array++) { + if (!nm_utils_parse_inaddr_bin(AF_INET, *array, NULL, &address_network) + || !address_network) { + _LOGW("invalid NameServer: %s", *array); + continue; } + any_good = TRUE; + _LOGI("DNS: %s", *array); + nm_l3_config_data_add_nameserver(priv->l3cd_4, AF_INET, &address_network); } - - if (iter == array) { + if (!any_good) { _LOGW("Settings: 'DomainNameServers': none specified"); - g_free(array); goto out; } - g_free(array); } if (g_variant_lookup(v_dict, "MessageProxy", "&s", &s)) { _LOGI("MessageProxy: %s", s); if (s && nm_utils_parse_inaddr_bin(AF_INET, s, NULL, &address_network)) { - nm_modem_get_route_parameters(NM_MODEM(self), - &ip4_route_table, - &ip4_route_metric, - NULL, - NULL); - - { - const NMPlatformIP4Route mms_route = { - .network = address_network, - .plen = 32, - .gateway = gateway_network, - .table_coerced = nm_platform_route_table_coerce(ip4_route_table), - .metric = ip4_route_metric, - }; - - nm_ip4_config_add_route(priv->ip4_config, &mms_route, NULL); - } - } else { + const NMPlatformIP4Route mms_route = { + .network = address_network, + .plen = 32, + .gateway = gateway_network, + .table_any = TRUE, + .table_coerced = 0, + .metric_any = TRUE, + .metric = 0, + }; + + nm_l3_config_data_add_route_4(priv->l3cd_4, &mms_route); + } else _LOGW("invalid MessageProxy: %s", s); - } } ret = TRUE; out: + if (priv->l3cd_4) + nm_l3_config_data_seal(priv->l3cd_4); + if (nm_modem_get_state(NM_MODEM(self)) != NM_MODEM_STATE_CONNECTED) { _LOGI("emitting PREPARE_RESULT: %s", ret ? "TRUE" : "FALSE"); nm_modem_emit_prepare_result(NM_MODEM(self), @@ -893,7 +894,7 @@ out: static void context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, gpointer user_data) { - NMModemOfono * self = NM_MODEM_OFONO(user_data); + NMModemOfono *self = NM_MODEM_OFONO(user_data); gs_unref_variant GVariant *v_dict = NULL; _LOGD("PropertyChanged: %s", property); @@ -912,38 +913,43 @@ context_property_changed(GDBusProxy *proxy, const char *property, GVariant *v, g handle_settings(v_dict, user_data); } -static NMActStageReturn -static_stage3_ip4_config_start(NMModem * modem, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason) +static void +stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_method) { - NMModemOfono * self = NM_MODEM_OFONO(modem); - NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - GError * error = NULL; + NMModemOfono *self = NM_MODEM_OFONO(modem); + NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); + gs_free_error GError *error = NULL; - if (!priv->ip4_config) { - _LOGD("IP4 config not ready(?)"); - return NM_ACT_STAGE_RETURN_FAILURE; + _LOGD("IP4 config is done; setting modem_state -> CONNECTED"); + + if (!NM_IS_IPv4(addr_family) || ip_method == NM_MODEM_IP_METHOD_AUTO) { + nm_modem_emit_signal_new_config_success(modem, addr_family, NULL, TRUE, NULL); + goto out; } - _LOGD("IP4 config is done; setting modem_state -> CONNECTED"); - g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, priv->ip4_config, error); + if (!priv->l3cd_4) { + nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "IP config not received"); + nm_modem_emit_signal_new_config_failure(modem, + addr_family, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, + error); + goto out; + } - /* Signal listener takes ownership of the IP4Config */ - priv->ip4_config = NULL; + nm_modem_emit_signal_new_config_success(modem, addr_family, priv->l3cd_4, FALSE, NULL); +out: nm_modem_set_state(NM_MODEM(self), NM_MODEM_STATE_CONNECTED, nm_modem_state_to_string(NM_MODEM_STATE_CONNECTED)); - return NM_ACT_STAGE_RETURN_POSTPONE; } static void context_properties_cb(GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; - gs_free_error GError *error = NULL; + NMModemOfono *self; + NMModemOfonoPrivate *priv; + gs_free_error GError *error = NULL; gs_unref_variant GVariant *properties = NULL; gs_unref_variant GVariant *settings = NULL; gs_unref_variant GVariant *v_dict = NULL; @@ -1007,10 +1013,10 @@ error: static void context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy || g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1040,7 +1046,7 @@ context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) * clear it so that we can gate getting the IP config from oFono * on whether or not we have already received them */ - g_clear_object(&priv->ip4_config); + nm_clear_l3cd(&priv->l3cd_4); /* We need to directly query ConnectionContextinteface to get the current * property values */ @@ -1081,8 +1087,8 @@ static GHashTable * create_connect_properties(NMConnection *connection) { NMSettingGsm *setting; - GHashTable * properties; - const char * str; + GHashTable *properties; + const char *str; setting = nm_connection_get_setting_gsm(connection); properties = g_hash_table_new(nm_str_hash, g_str_equal); @@ -1103,14 +1109,14 @@ create_connect_properties(NMConnection *connection) } static NMActStageReturn -modem_act_stage1_prepare(NMModem * modem, - NMConnection * connection, +modem_act_stage1_prepare(NMModem *modem, + NMConnection *connection, NMDeviceStateReason *out_failure_reason) { - NMModemOfono * self = NM_MODEM_OFONO(modem); + NMModemOfono *self = NM_MODEM_OFONO(modem); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); - const char * context_id; - char ** id = NULL; + const char *context_id; + char **id = NULL; context_id = nm_connection_get_id(connection); id = g_strsplit(context_id, "/", 0); @@ -1149,10 +1155,10 @@ modem_act_stage1_prepare(NMModem * modem, static void modem_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - NMModemOfono * self; - NMModemOfonoPrivate *priv; + NMModemOfono *self; + NMModemOfonoPrivate *priv; gs_free_error GError *error = NULL; - GDBusProxy * proxy; + GDBusProxy *proxy; proxy = g_dbus_proxy_new_for_bus_finish(result, &error); if (!proxy && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) @@ -1194,7 +1200,7 @@ nm_modem_ofono_init(NMModemOfono *self) static void constructed(GObject *object) { - NMModemOfono * self = NM_MODEM_OFONO(object); + NMModemOfono *self = NM_MODEM_OFONO(object); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); priv->modem_proxy_cancellable = g_cancellable_new(); @@ -1245,7 +1251,7 @@ nm_modem_ofono_new(const char *path) static void dispose(GObject *object) { - NMModemOfono * self = NM_MODEM_OFONO(object); + NMModemOfono *self = NM_MODEM_OFONO(object); NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self); nm_clear_g_cancellable(&priv->modem_proxy_cancellable); @@ -1258,7 +1264,7 @@ dispose(GObject *object) priv->connect_properties = NULL; } - g_clear_object(&priv->ip4_config); + nm_clear_l3cd(&priv->l3cd_4); if (priv->modem_proxy) { g_signal_handlers_disconnect_by_data(priv->modem_proxy, self); @@ -1300,6 +1306,6 @@ nm_modem_ofono_class_init(NMModemOfonoClass *klass) modem_class->deactivate_cleanup = deactivate_cleanup; modem_class->check_connection_compatible_with_modem = check_connection_compatible_with_modem; - modem_class->modem_act_stage1_prepare = modem_act_stage1_prepare; - modem_class->static_stage3_ip4_config_start = static_stage3_ip4_config_start; + modem_class->modem_act_stage1_prepare = modem_act_stage1_prepare; + modem_class->stage3_ip_config_start = stage3_ip_config_start; } diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c index ccea69db..a5ee8ce8 100644 --- a/src/core/devices/wwan/nm-modem.c +++ b/src/core/devices/wwan/nm-modem.c @@ -13,16 +13,16 @@ #include <linux/if.h> #include <linux/rtnetlink.h> -#include "libnm-core-intern/nm-core-internal.h" -#include "libnm-platform/nm-platform.h" -#include "nm-setting-connection.h" #include "NetworkManagerUtils.h" #include "devices/nm-device-private.h" -#include "nm-netns.h" +#include "libnm-core-intern/nm-core-internal.h" +#include "libnm-platform/nm-platform.h" #include "nm-act-request.h" -#include "nm-ip4-config.h" -#include "nm-ip6-config.h" +#include "nm-l3-config-data.h" +#include "nm-netns.h" +#include "nm-setting-connection.h" #include "ppp/nm-ppp-manager-call.h" +#include "ppp/nm-ppp-mgr.h" #include "ppp/nm-ppp-status.h" /*****************************************************************************/ @@ -45,8 +45,7 @@ enum { PPP_STATS, PPP_FAILED, PREPARE_RESULT, - IP4_CONFIG_RESULT, - IP6_CONFIG_RESULT, + NEW_CONFIG, AUTH_REQUESTED, AUTH_RESULT, REMOVED, @@ -56,6 +55,11 @@ enum { static guint signals[LAST_SIGNAL] = {0}; +typedef struct { + GSource *stage3_on_idle_source; + bool stage3_started : 1; +} IPData; + typedef struct _NMModemPrivate { char *uid; char *path; @@ -63,41 +67,38 @@ typedef struct _NMModemPrivate { char *control_port; char *data_port; - /* TODO: ip_iface is solely used for nm_modem_owns_port(). - * We should rework the code that it's not necessary */ - char *ip_iface; - - int ip_ifindex; - NMModemIPMethod ip4_method; - NMModemIPMethod ip6_method; - NMUtilsIPv6IfaceId iid; - NMModemState state; - NMModemState prev_state; /* revert to this state if enable/disable fails */ - char * device_id; - char * sim_id; - NMModemIPType ip_types; - char * sim_operator_id; - char * operator_code; - char * apn; + int ip_ifindex; + NMModemIPMethod ip4_method; + NMModemIPMethod ip6_method; + NMModemState state; + NMModemState prev_state; /* revert to this state if enable/disable fails */ + char *device_id; + char *sim_id; + NMModemIPType ip_types; + char *sim_operator_id; + char *operator_code; + char *apn; NMPPPManager *ppp_manager; + NMPppMgr *ppp_mgr; - NMActRequest * act_request; + NMActRequest *act_req; + NMDevice *device; guint32 secrets_tries; NMActRequestGetSecretsCallId *secrets_id; guint mm_ip_timeout; - guint32 ip4_route_table; - guint32 ip4_route_metric; - guint32 ip6_route_table; - guint32 ip6_route_metric; + bool claimed : 1; - /* PPP stats */ - guint32 in_bytes; - guint32 out_bytes; + union { + struct { + IPData ip_data_6; + IPData ip_data_4; + }; + IPData ip_data_x[2]; + }; - bool claimed : 1; } NMModemPrivate; G_DEFINE_TYPE(NMModem, nm_modem, G_TYPE_OBJECT) @@ -149,7 +150,7 @@ _nmlog_prefix(char *prefix, NMModem *self) /*****************************************************************************/ -static void _set_ip_ifindex(NMModem *self, int ifindex, const char *ifname); +static void _set_ip_ifindex(NMModem *self, int ifindex); /*****************************************************************************/ /* State/enabled/connected */ @@ -180,6 +181,91 @@ nm_modem_state_to_string(NMModemState state) /*****************************************************************************/ +static NMPlatform * +_get_platform(NMModem *self) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + + if (!priv->device) + return NULL; + + return nm_device_get_platform(priv->device); +} + +/*****************************************************************************/ + +void +nm_modem_emit_signal_new_config(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid, + NMDeviceStateReason failure_reason, + GError *error) +{ + nm_assert(NM_IS_MODEM(self)); + nm_assert_addr_family(addr_family); + nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd)); + nm_assert(!do_auto || addr_family == AF_INET6); + nm_assert(!iid || addr_family == AF_INET6); + nm_assert(!error || (!l3cd && !do_auto && !iid)); + + if (error) { + _LOGD("signal: new-config: IPv%c, failed '%s', %s", + nm_utils_addr_family_to_char(addr_family), + nm_device_state_reason_to_string_a(failure_reason), + error->message); + } else { + gs_free char *str_to_free = NULL; + + _LOGD( + "signal: new-config: IPv%c%s%s%s%s", + nm_utils_addr_family_to_char(addr_family), + l3cd ? ", has-l3cd" : "", + do_auto ? ", do-auto" : "", + NM_PRINT_FMT_QUOTED2(iid, + ", iid=", + nm_utils_bin2hexstr_a(iid, sizeof(*iid), ':', FALSE, &str_to_free), + "")); + } + + g_signal_emit(self, + signals[NEW_CONFIG], + 0, + addr_family, + nm_l3_config_data_seal(l3cd), + do_auto, + iid, + (int) failure_reason, + error); +} + +void +nm_modem_emit_signal_new_config_success(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid) +{ + nm_modem_emit_signal_new_config(self, + addr_family, + l3cd, + do_auto, + iid, + NM_DEVICE_STATE_REASON_NONE, + NULL); +} + +void +nm_modem_emit_signal_new_config_failure(NMModem *self, + int addr_family, + NMDeviceStateReason failure_reason, + GError *error) +{ + nm_assert(error); + nm_modem_emit_signal_new_config(self, addr_family, NULL, FALSE, NULL, failure_reason, error); +} + gboolean nm_modem_is_claimed(NMModem *self) { @@ -240,10 +326,10 @@ nm_modem_set_state(NMModem *self, NMModemState new_state, const char *reason) priv->prev_state = NM_MODEM_STATE_UNKNOWN; if (new_state != old_state) { - _LOGI("modem state changed, '%s' --> '%s' (reason: %s)", + _LOGD("signal: modem state changed, '%s' --> '%s' (reason: %s%s%s)", nm_modem_state_to_string(old_state), nm_modem_state_to_string(new_state), - reason ?: "none"); + NM_PRINT_FMT_QUOTE_STRING(reason)); priv->state = new_state; _notify(self, PROP_STATE); @@ -285,7 +371,7 @@ nm_modem_set_mm_enabled(NMModem *self, gboolean enabled) /* Try to unlock the modem if it's being enabled */ if (enabled) - g_signal_emit(self, signals[AUTH_REQUESTED], 0); + nm_modem_emit_auth_requested(self); return; } @@ -303,14 +389,25 @@ nm_modem_set_mm_enabled(NMModem *self, gboolean enabled) void nm_modem_emit_removed(NMModem *self) { + _LOGD("signal: removed"); g_signal_emit(self, signals[REMOVED], 0); } void +nm_modem_emit_auth_requested(NMModem *self) +{ + _LOGD("signal: auth-requested"); + g_signal_emit(self, signals[AUTH_REQUESTED], 0); +} + +void nm_modem_emit_prepare_result(NMModem *self, gboolean success, NMDeviceStateReason reason) { nm_assert(NM_IS_MODEM(self)); + _LOGD("signal: prepare-result: %s (%s)", + success ? "success" : "failure", + nm_device_state_reason_to_string_a(reason)); g_signal_emit(self, signals[PREPARE_RESULT], 0, success, (guint) reason); } @@ -319,6 +416,7 @@ nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason) { nm_assert(NM_IS_MODEM(self)); + _LOGD("signal: ppp-failed (%s)", nm_device_state_reason_to_string_a(reason)); g_signal_emit(self, signals[PPP_FAILED], 0, (guint) reason); } @@ -363,16 +461,16 @@ build_single_ip_type_array(NMModemIPType type) GArray * nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError **error) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); NMSettingIPConfig *s_ip4, *s_ip6; - const char * method; + const char *method; gboolean ip4 = TRUE, ip6 = TRUE; gboolean ip4_may_fail = TRUE, ip6_may_fail = TRUE; s_ip4 = nm_connection_get_setting_ip4_config(connection); if (s_ip4) { method = nm_setting_ip_config_get_method(s_ip4); - if (g_strcmp0(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) + if (nm_streq0(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) ip4 = FALSE; ip4_may_fail = nm_setting_ip_config_get_may_fail(s_ip4); } @@ -413,7 +511,7 @@ nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError if (ip4 && ip6) { NMModemIPType type; - GArray * out; + GArray *out; out = g_array_sized_new(FALSE, FALSE, sizeof(NMModemIPType), 3); @@ -487,83 +585,101 @@ nm_modem_get_apn(NMModem *self) } /*****************************************************************************/ -/* IP method PPP */ static void -ppp_state_changed(NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +_ppp_mgr_cleanup(NMModem *self) { - switch (status) { - case NM_PPP_STATUS_DISCONNECT: - nm_modem_emit_ppp_failed(user_data, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); - break; - case NM_PPP_STATUS_DEAD: - nm_modem_emit_ppp_failed(user_data, NM_DEVICE_STATE_REASON_PPP_FAILED); - break; - default: - break; - } + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + + nm_clear_pointer(&priv->ppp_mgr, nm_ppp_mgr_destroy); } static void -ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpointer user_data) +_ppp_maybe_emit_new_config(NMModem *self, int addr_family) { - NMModem *self = NM_MODEM(user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMPppMgrIPData *ip_data; + gboolean do_auto; - nm_assert(ifindex >= 0); - nm_assert(NM_MODEM_GET_PRIVATE(self)->ppp_manager == ppp_manager); + ip_data = nm_ppp_mgr_get_ip_data(priv->ppp_mgr, addr_family); - if (ifindex <= 0 && iface) { - /* this might happen, if the ifname was already deleted - * and we failed to resolve ifindex. - * - * Forget about the name. */ - iface = NULL; + if (!ip_data->ip_received) + return; + + if (IS_IPv4) + do_auto = FALSE; + else { + do_auto = !ip_data->l3cd + || (!nm_l3_config_data_get_first_obj(ip_data->l3cd, + NMP_OBJECT_TYPE_IP6_ADDRESS, + nmp_object_ip6_address_is_not_link_local)); } - _set_ip_ifindex(self, ifindex, iface); -} -static void -ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data) -{ - NMModem *self = NM_MODEM(user_data); + nm_assert(!IS_IPv4 || !ip_data->ipv6_iid); - g_signal_emit(self, signals[IP4_CONFIG_RESULT], 0, config, NULL); + nm_modem_emit_signal_new_config_success(self, + addr_family, + ip_data->l3cd, + do_auto, + ip_data->ipv6_iid); } static void -ppp_ip6_config(NMPPPManager * ppp_manager, - const NMUtilsIPv6IfaceId *iid, - NMIP6Config * config, - gpointer user_data) +_ppp_mgr_callback(NMPppMgr *ppp_mgr, const NMPppMgrCallbackData *callback_data, gpointer user_data) { - NMModem *self = NM_MODEM(user_data); + NMModem *self = NM_MODEM(user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + int IS_IPv4; - NM_MODEM_GET_PRIVATE(self)->iid = *iid; + switch (callback_data->callback_type) { + case NM_PPP_MGR_CALLBACK_TYPE_STATE_CHANGED: - nm_modem_emit_ip6_config_result(self, config, NULL); -} + if (callback_data->data.state >= _NM_PPP_MGR_STATE_FAILED_START) { + nm_modem_emit_ppp_failed(self, callback_data->data.reason); + return; + } -static void -ppp_stats(NMPPPManager *ppp_manager, guint i_in_bytes, guint i_out_bytes, gpointer user_data) -{ - NMModem * self = NM_MODEM(user_data); - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - guint32 in_bytes = i_in_bytes; - guint32 out_bytes = i_out_bytes; + if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IFINDEX) + _set_ip_ifindex(self, callback_data->data.ifindex); + + if (callback_data->data.state >= NM_PPP_MGR_STATE_HAVE_IP_CONFIG) { + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + if (!priv->ip_data_x[IS_IPv4].stage3_started) { + /* stage3 didn't yet start. We don't emit the IP signal yet. + * We will emit it together with stage3. */ + continue; + } + if (priv->ip_data_x[IS_IPv4].stage3_on_idle_source) { + /* We scheduled already a handler. Let it handle the new configuration. */ + continue; + } + if (callback_data->data.ip_changed_x[IS_IPv4]) + _ppp_maybe_emit_new_config(self, IS_IPv4 ? AF_INET : AF_INET6); + } + } + return; - if (priv->in_bytes != in_bytes || priv->out_bytes != out_bytes) { - priv->in_bytes = in_bytes; - priv->out_bytes = out_bytes; - g_signal_emit(self, signals[PPP_STATS], 0, (guint) in_bytes, (guint) out_bytes); + case NM_PPP_MGR_CALLBACK_TYPE_STATS_CHANGED: + g_signal_emit(self, + signals[PPP_STATS], + 0, + (guint) callback_data->data.stats_data->in_bytes, + (guint) callback_data->data.stats_data->out_bytes); + return; } + + nm_assert_not_reached(); } +/*****************************************************************************/ + static gboolean port_speed_is_zero(const char *port) { struct termios options; nm_auto_close int fd = -1; - gs_free char * path = NULL; + gs_free char *path = NULL; nm_assert(port); @@ -585,291 +701,116 @@ port_speed_is_zero(const char *port) return cfgetospeed(&options) == B0; } -static NMActStageReturn -ppp_stage3_ip_config_start(NMModem * self, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - const char * ppp_name = NULL; - GError * error = NULL; - guint ip_timeout = 30; - guint baud_override = 0; - - g_return_val_if_fail(NM_IS_MODEM(self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail(NM_IS_ACT_REQUEST(req), NM_ACT_STAGE_RETURN_FAILURE); - - /* If we're already running PPP don't restart it; for example, if both - * IPv4 and IPv6 are requested, IPv4 gets started first, but we use the - * same pppd for both v4 and v6. - */ - if (priv->ppp_manager) - return NM_ACT_STAGE_RETURN_POSTPONE; - - if (NM_MODEM_GET_CLASS(self)->get_user_pass) { - NMConnection *connection = nm_act_request_get_applied_connection(req); - - g_assert(connection); - if (!NM_MODEM_GET_CLASS(self)->get_user_pass(self, connection, &ppp_name, NULL)) - return NM_ACT_STAGE_RETURN_FAILURE; - } - - if (!priv->data_port) { - _LOGE("error starting PPP (no data port)"); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - - /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, - * use the default one (30s) */ - if (priv->mm_ip_timeout > 0) { - _LOGI("using modem-specified IP timeout: %u seconds", priv->mm_ip_timeout); - ip_timeout = priv->mm_ip_timeout; - } - - /* Some tty drivers and modems ignore port speed, but pppd requires the - * port speed to be > 0 or it exits. If the port speed is 0 pass an - * explicit speed to pppd to prevent the exit. - * https://bugzilla.redhat.com/show_bug.cgi?id=1281731 - */ - if (port_speed_is_zero(priv->data_port)) - baud_override = 57600; - - priv->ppp_manager = nm_ppp_manager_create(priv->data_port, &error); - - if (priv->ppp_manager) { - nm_ppp_manager_set_route_parameters(priv->ppp_manager, - priv->ip4_route_table, - priv->ip4_route_metric, - priv->ip6_route_table, - priv->ip6_route_metric); - } - - if (!priv->ppp_manager - || !nm_ppp_manager_start(priv->ppp_manager, - req, - ppp_name, - ip_timeout, - baud_override, - &error)) { - _LOGE("error starting PPP: %s", error->message); - g_error_free(error); - g_clear_object(&priv->ppp_manager); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); - return NM_ACT_STAGE_RETURN_FAILURE; - } - - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_STATE_CHANGED, - G_CALLBACK(ppp_state_changed), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, - G_CALLBACK(ppp_ifindex_set), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, - G_CALLBACK(ppp_ip4_config), - self); - g_signal_connect(priv->ppp_manager, - NM_PPP_MANAGER_SIGNAL_IP6_CONFIG, - G_CALLBACK(ppp_ip6_config), - self); - g_signal_connect(priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATS, G_CALLBACK(ppp_stats), self); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - /*****************************************************************************/ -NMActStageReturn -nm_modem_stage3_ip4_config_start(NMModem * self, - NMDevice * device, - gboolean * out_autoip4, - NMDeviceStateReason *out_failure_reason) +static gboolean +_stage3_ip_config_start_on_idle(NMModem *self, int addr_family) { - NMModemPrivate * priv; - NMActRequest * req; - NMConnection * connection; - const char * method; - NMActStageReturn ret; - - _LOGD("ip4_config_start"); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + NMModemIPMethod ip_method; + NMConnection *connection; + const char *method; + gs_free_error GError *error = NULL; + NMDeviceStateReason failure_reason; - g_return_val_if_fail(NM_IS_MODEM(self), NM_ACT_STAGE_RETURN_FAILURE); - g_return_val_if_fail(NM_IS_DEVICE(device), NM_ACT_STAGE_RETURN_FAILURE); - nm_assert(out_autoip4 && !*out_autoip4); - - req = nm_device_get_act_request(device); - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection(req); - g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].stage3_on_idle_source); - nm_modem_set_route_parameters_from_device(self, device); + connection = nm_act_request_get_applied_connection(priv->act_req); + g_return_val_if_fail(connection, G_SOURCE_CONTINUE); - method = nm_utils_get_ip_config_method(connection, AF_INET); + method = nm_utils_get_ip_config_method(connection, addr_family); - /* Only Disabled and Auto methods make sense for WWAN */ - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) - return NM_ACT_STAGE_RETURN_SUCCESS; + if (IS_IPv4 ? NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) + : NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { + nm_modem_emit_signal_new_config_success(self, addr_family, NULL, FALSE, NULL); + return G_SOURCE_CONTINUE; + } - if (!nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { - _LOGE("unhandled WWAN IPv4 method '%s'; will fail", method); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED); - return NM_ACT_STAGE_RETURN_FAILURE; + if (!nm_streq(method, + IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_AUTO + : NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { + failure_reason = NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED; + nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "ip method unsupported by modem"); + goto out_failure; } - priv = NM_MODEM_GET_PRIVATE(self); - switch (priv->ip4_method) { + ip_method = IS_IPv4 ? priv->ip4_method : priv->ip6_method; + + switch (ip_method) { case NM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip_config_start(self, req, out_failure_reason); - break; + _ppp_maybe_emit_new_config(self, addr_family); + return G_SOURCE_CONTINUE; case NM_MODEM_IP_METHOD_STATIC: - _LOGD("MODEM_IP_METHOD_STATIC"); - ret = - NM_MODEM_GET_CLASS(self)->static_stage3_ip4_config_start(self, req, out_failure_reason); - break; case NM_MODEM_IP_METHOD_AUTO: - _LOGD("MODEM_IP_METHOD_AUTO"); - *out_autoip4 = TRUE; - ret = NM_ACT_STAGE_RETURN_SUCCESS; - break; + NM_MODEM_GET_CLASS(self)->stage3_ip_config_start(self, addr_family, ip_method); + return G_SOURCE_CONTINUE; default: - _LOGI("IPv4 configuration disabled"); - ret = NM_ACT_STAGE_RETURN_IP_FAIL; - break; + failure_reason = NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED; + nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "modem IP method unsupported"); + goto out_failure; } - return ret; -} - -void -nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config) -{ - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(modem); + nm_assert_not_reached(); - /* If the modem has an ethernet-type data interface (ie, not PPP and thus - * not point-to-point) and IP config has a /32 prefix, then we assume that - * ARP will be pointless and we turn it off. - */ - if (priv->ip4_method == NM_MODEM_IP_METHOD_STATIC - || priv->ip4_method == NM_MODEM_IP_METHOD_AUTO) { - const NMPlatformIP4Address *address = nm_ip4_config_get_first_address(config); - - g_assert(address); - if (address->plen == 32) - nm_platform_link_change_flags(nm_device_get_platform(device), - nm_device_get_ip_ifindex(device), - IFF_NOARP, - TRUE); - } +out_failure: + nm_modem_emit_signal_new_config_failure(self, addr_family, failure_reason, error); + return G_SOURCE_CONTINUE; } -/*****************************************************************************/ - -void -nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error) +static gboolean +_stage3_ip_config_start_on_idle_4(gpointer user_data) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); - NMDedupMultiIter ipconf_iter; - const NMPlatformIP6Address *addr; - gboolean do_slaac = TRUE; - - if (error) { - g_signal_emit(self, signals[IP6_CONFIG_RESULT], 0, NULL, FALSE, error); - return; - } - - if (config) { - /* If the IPv6 configuration only included a Link-Local address, then - * we have to run SLAAC to get the full IPv6 configuration. - */ - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, config, &addr) { - if (IN6_IS_ADDR_LINKLOCAL(&addr->address)) { - if (!priv->iid.id) - priv->iid.id = ((guint64 *) (&addr->address.s6_addr))[1]; - } else - do_slaac = FALSE; - } - } - g_assert(config || do_slaac); - - g_signal_emit(self, signals[IP6_CONFIG_RESULT], 0, config, do_slaac, NULL); + return _stage3_ip_config_start_on_idle(user_data, AF_INET); } -static NMActStageReturn -stage3_ip6_config_request(NMModem *self, NMDeviceStateReason *out_failure_reason) +static gboolean +_stage3_ip_config_start_on_idle_6(gpointer user_data) { - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return NM_ACT_STAGE_RETURN_FAILURE; + return _stage3_ip_config_start_on_idle(user_data, AF_INET6); } -NMActStageReturn -nm_modem_stage3_ip6_config_start(NMModem * self, - NMDevice * device, - NMDeviceStateReason *out_failure_reason) +gboolean +nm_modem_stage3_ip_config_start(NMModem *self, int addr_family, NMDevice *device) { - NMModemPrivate * priv; - NMActRequest * req; - NMActStageReturn ret; - NMConnection * connection; - const char * method; - - g_return_val_if_fail(NM_IS_MODEM(self), NM_ACT_STAGE_RETURN_FAILURE); - - req = nm_device_get_act_request(device); - g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); - - connection = nm_act_request_get_applied_connection(req); - g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMModemPrivate *priv; - nm_modem_set_route_parameters_from_device(self, device); + g_return_val_if_fail(NM_IS_MODEM(self), FALSE); + g_return_val_if_fail(NM_IS_DEVICE(device), FALSE); - method = nm_utils_get_ip_config_method(connection, AF_INET6); + priv = NM_MODEM_GET_PRIVATE(self); - /* Only Ignore, Disabled and Auto methods make sense for WWAN */ - if (NM_IN_STRSET(method, - NM_SETTING_IP6_CONFIG_METHOD_IGNORE, - NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) - return NM_ACT_STAGE_RETURN_IP_DONE; + g_return_val_if_fail(priv->device == device, FALSE); - if (!nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { - _LOGW("unhandled WWAN IPv6 method '%s'; will fail", method); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return NM_ACT_STAGE_RETURN_FAILURE; + if (priv->ip_data_x[IS_IPv4].stage3_started) { + /* we already started. Nothing to do. */ + return FALSE; } - priv = NM_MODEM_GET_PRIVATE(self); - switch (priv->ip6_method) { - case NM_MODEM_IP_METHOD_PPP: - ret = ppp_stage3_ip_config_start(self, req, out_failure_reason); - break; - case NM_MODEM_IP_METHOD_STATIC: - case NM_MODEM_IP_METHOD_AUTO: - /* Both static and DHCP/Auto retrieve a base IP config from the modem - * which in the static case is the full config, and the DHCP/Auto case - * is just the IPv6LL address to use for SLAAC. - */ - ret = NM_MODEM_GET_CLASS(self)->stage3_ip6_config_request(self, out_failure_reason); - break; - default: - _LOGI("IPv6 configuration disabled"); - ret = NM_ACT_STAGE_RETURN_IP_FAIL; - break; - } + nm_assert(!priv->ppp_mgr + || nm_ppp_mgr_get_state(priv->ppp_mgr) >= NM_PPP_MGR_STATE_HAVE_IFINDEX); + + priv->ip_data_x[IS_IPv4].stage3_started = TRUE; - return ret; + priv->ip_data_x[IS_IPv4].stage3_on_idle_source = nm_g_idle_add_source( + IS_IPv4 ? _stage3_ip_config_start_on_idle_4 : _stage3_ip_config_start_on_idle_6, + self); + return TRUE; } +/*****************************************************************************/ + guint32 nm_modem_get_configured_mtu(NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force) { NMConnection *connection; - NMSetting * setting; + NMSetting *setting; gint64 mtu_default; guint mtu = 0; - const char * property_name; + const char *property_name; nm_assert(NM_IS_DEVICE(self)); nm_assert(out_source); @@ -910,17 +851,17 @@ cancel_get_secrets(NMModem *self) NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); if (priv->secrets_id) - nm_act_request_cancel_secrets(priv->act_request, priv->secrets_id); + nm_act_request_cancel_secrets(priv->act_req, priv->secrets_id); } static void -modem_secrets_cb(NMActRequest * req, +modem_secrets_cb(NMActRequest *req, NMActRequestGetSecretsCallId *call_id, - NMSettingsConnection * connection, - GError * error, + NMSettingsConnection *connection, + GError *error, gpointer user_data) { - NMModem * self = NM_MODEM(user_data); + NMModem *self = NM_MODEM(user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); g_return_if_fail(call_id == priv->secrets_id); @@ -934,23 +875,25 @@ modem_secrets_cb(NMActRequest * req, if (error) _LOGW("modem-secrets: %s", error->message); + _LOGD("signal: auth-result: %s%s", + NM_PRINT_FMT_QUOTED2(error, "failed: ", error->message, "success")); g_signal_emit(self, signals[AUTH_RESULT], 0, error); } void -nm_modem_get_secrets(NMModem * self, +nm_modem_get_secrets(NMModem *self, const char *setting_name, gboolean request_new, const char *hint) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; cancel_get_secrets(self); if (request_new) flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - priv->secrets_id = nm_act_request_get_secrets(priv->act_request, + priv->secrets_id = nm_act_request_get_secrets(priv->act_req, FALSE, setting_name, flags, @@ -958,14 +901,14 @@ nm_modem_get_secrets(NMModem * self, modem_secrets_cb, self); g_return_if_fail(priv->secrets_id); - g_signal_emit(self, signals[AUTH_REQUESTED], 0); + nm_modem_emit_auth_requested(self); } /*****************************************************************************/ static NMActStageReturn -modem_act_stage1_prepare(NMModem * modem, - NMConnection * connection, +modem_act_stage1_prepare(NMModem *modem, + NMConnection *connection, NMDeviceStateReason *out_failure_reason) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_UNKNOWN); @@ -973,25 +916,28 @@ modem_act_stage1_prepare(NMModem * modem, } NMActStageReturn -nm_modem_act_stage1_prepare(NMModem * self, - NMActRequest * req, +nm_modem_act_stage1_prepare(NMModem *self, + NMActRequest *req, NMDeviceStateReason *out_failure_reason) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); gs_unref_ptrarray GPtrArray *hints = NULL; - const char * setting_name = NULL; + const char *setting_name = NULL; NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; - NMConnection * connection; + NMConnection *connection; + NMDevice *device; g_return_val_if_fail(NM_IS_ACT_REQUEST(req), NM_ACT_STAGE_RETURN_FAILURE); - if (priv->act_request) - g_object_unref(priv->act_request); - priv->act_request = g_object_ref(req); + nm_g_object_ref_set(&priv->act_req, req); + device = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(priv->act_req)); + g_return_val_if_fail(NM_IS_DEVICE(device), NM_ACT_STAGE_RETURN_FAILURE); connection = nm_act_request_get_applied_connection(req); g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + nm_g_object_ref_set(&priv->device, device); + setting_name = nm_connection_need_secrets(connection, &hints); if (!setting_name) { nm_assert(!hints); @@ -1015,24 +961,99 @@ nm_modem_act_stage1_prepare(NMModem * self, modem_secrets_cb, self); g_return_val_if_fail(priv->secrets_id, NM_ACT_STAGE_RETURN_FAILURE); - g_signal_emit(self, signals[AUTH_REQUESTED], 0); + nm_modem_emit_auth_requested(self); return NM_ACT_STAGE_RETURN_POSTPONE; } /*****************************************************************************/ -void -nm_modem_act_stage2_config(NMModem *self) +NMActStageReturn +nm_modem_act_stage2_config(NMModem *self, NMDevice *device, NMDeviceStateReason *out_failure_reason) { NMModemPrivate *priv; + gboolean needs_ppp; - g_return_if_fail(NM_IS_MODEM(self)); + g_return_val_if_fail(NM_IS_MODEM(self), NM_ACT_STAGE_RETURN_FAILURE); + g_return_val_if_fail(NM_IS_DEVICE(device), NM_ACT_STAGE_RETURN_FAILURE); priv = NM_MODEM_GET_PRIVATE(self); + + g_return_val_if_fail(priv->device == device, NM_ACT_STAGE_RETURN_FAILURE); + /* Clear secrets tries counter since secrets were successfully used * already if we get here. */ priv->secrets_tries = 0; + + needs_ppp = + (priv->ip4_method == NM_MODEM_IP_METHOD_PPP || priv->ip6_method == NM_MODEM_IP_METHOD_PPP); + + if (needs_ppp && !priv->ppp_mgr) { + const char *ppp_name = NULL; + gs_free_error GError *error = NULL; + guint ip_timeout; + guint baud_override; + NMActRequest *req; + + req = nm_device_get_act_request(device); + g_return_val_if_fail(req, NM_ACT_STAGE_RETURN_FAILURE); + + if (NM_MODEM_GET_CLASS(self)->get_user_pass) { + NMConnection *connection = nm_act_request_get_applied_connection(req); + + g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE); + if (!NM_MODEM_GET_CLASS(self)->get_user_pass(self, connection, &ppp_name, NULL)) + return NM_ACT_STAGE_RETURN_FAILURE; + } + + if (!priv->data_port) { + _LOGW("error starting PPP (no data port)"); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_PPP_START_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* Check if ModemManager requested a specific IP timeout to be used. If 0 reported, + * use the default one (30s) */ + if (priv->mm_ip_timeout > 0) { + _LOGI("using modem-specified IP timeout: %u seconds", priv->mm_ip_timeout); + ip_timeout = priv->mm_ip_timeout; + } else + ip_timeout = 30; + + /* Some tty drivers and modems ignore port speed, but pppd requires the + * port speed to be > 0 or it exits. If the port speed is 0 pass an + * explicit speed to pppd to prevent the exit. + * https://bugzilla.redhat.com/show_bug.cgi?id=1281731 + */ + if (port_speed_is_zero(priv->data_port)) + baud_override = 57600; + else + baud_override = 0; + + priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){ + .netns = nm_device_get_netns(device), + .parent_iface = priv->data_port, + .callback = _ppp_mgr_callback, + .user_data = self, + .act_req = req, + .ppp_username = ppp_name, + .timeout_secs = ip_timeout, + .baud_override = baud_override, + }), + &error); + if (!priv->ppp_mgr) { + _LOGW("PPP failed to start: %s", error->message); + *out_failure_reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; + } + + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + if (needs_ppp && nm_ppp_mgr_get_state(priv->ppp_mgr) < NM_PPP_MGR_STATE_HAVE_IFINDEX) + return NM_ACT_STAGE_RETURN_POSTPONE; + + return NM_ACT_STAGE_RETURN_SUCCESS; } /*****************************************************************************/ @@ -1044,7 +1065,7 @@ nm_modem_check_connection_compatible(NMModem *self, NMConnection *connection, GE if (nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_GSM_SETTING_NAME)) { NMSettingGsm *s_gsm; - const char * str; + const char *str; s_gsm = _nm_connection_check_main_setting(connection, NM_SETTING_GSM_SETTING_NAME, error); if (!s_gsm) @@ -1098,11 +1119,11 @@ nm_modem_check_connection_compatible(NMModem *self, NMConnection *connection, GE /*****************************************************************************/ gboolean -nm_modem_complete_connection(NMModem * self, - const char * iface, - NMConnection * connection, +nm_modem_complete_connection(NMModem *self, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error) + GError **error) { NMModemClass *klass; @@ -1126,27 +1147,26 @@ deactivate_cleanup(NMModem *self, NMDevice *device, gboolean stop_ppp_manager) { NMModemPrivate *priv; int ifindex; + int IS_IPv4; g_return_if_fail(NM_IS_MODEM(self)); priv = NM_MODEM_GET_PRIVATE(self); + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + priv->ip_data_x[IS_IPv4].stage3_started = FALSE; + nm_clear_g_source_inst(&priv->ip_data_x[IS_IPv4].stage3_on_idle_source); + } + priv->secrets_tries = 0; - if (priv->act_request) { + if (priv->act_req) { cancel_get_secrets(self); - g_object_unref(priv->act_request); - priv->act_request = NULL; + g_clear_object(&priv->act_req); } + g_clear_object(&priv->device); - priv->in_bytes = priv->out_bytes = 0; - - if (priv->ppp_manager) { - g_signal_handlers_disconnect_by_data(priv->ppp_manager, self); - if (stop_ppp_manager) - nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL); - g_clear_object(&priv->ppp_manager); - } + _ppp_mgr_cleanup(self); if (device) { g_return_if_fail(NM_IS_DEVICE(device)); @@ -1170,15 +1190,15 @@ deactivate_cleanup(NMModem *self, NMDevice *device, gboolean stop_ppp_manager) priv->mm_ip_timeout = 0; priv->ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; priv->ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - _set_ip_ifindex(self, -1, NULL); + _set_ip_ifindex(self, -1); } /*****************************************************************************/ typedef struct { - NMModem * self; - NMDevice * device; - GCancellable * cancellable; + NMModem *self; + NMDevice *device; + GCancellable *cancellable; NMModemDeactivateCallback callback; gpointer callback_user_data; } DeactivateContext; @@ -1216,7 +1236,7 @@ _deactivate_call_disconnect(DeactivateContext *ctx) } static void -_deactivate_ppp_manager_stop_cb(NMPPPManager * ppp_manager, +_deactivate_ppp_manager_stop_cb(NMPPPManager *ppp_manager, NMPPPManagerStopHandle *handle, gboolean was_cancelled, gpointer user_data) @@ -1239,15 +1259,15 @@ _deactivate_ppp_manager_stop_cb(NMPPPManager * ppp_manager, } void -nm_modem_deactivate_async(NMModem * self, - NMDevice * device, - GCancellable * cancellable, +nm_modem_deactivate_async(NMModem *self, + NMDevice *device, + GCancellable *cancellable, NMModemDeactivateCallback callback, gpointer user_data) { - NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); DeactivateContext *ctx; - NMPPPManager * ppp_manager; + NMPPPManager *ppp_manager; g_return_if_fail(NM_IS_MODEM(self)); g_return_if_fail(NM_IS_DEVICE(device)); @@ -1307,11 +1327,11 @@ nm_modem_device_state_changed(NMModem *self, NMDeviceState new_state, NMDeviceSt case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_DISCONNECTED: - if (priv->act_request) { + if (priv->act_req) { cancel_get_secrets(self); - g_object_unref(priv->act_request); - priv->act_request = NULL; + g_clear_object(&priv->act_req); } + g_clear_object(&priv->device); if (was_connected) { /* Don't bother warning on FAILED since the modem is already gone */ @@ -1377,32 +1397,27 @@ nm_modem_get_ip_ifindex(NMModem *self) } static void -_set_ip_ifindex(NMModem *self, int ifindex, const char *ifname) +_set_ip_ifindex(NMModem *self, int ifindex) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); nm_assert(ifindex >= -1); - nm_assert((ifindex > 0) == !!ifname); - - if (!nm_streq0(priv->ip_iface, ifname)) { - g_free(priv->ip_iface); - priv->ip_iface = g_strdup(ifname); - } if (priv->ip_ifindex != ifindex) { + _LOGD("signal: ifindex changed: %d", ifindex); priv->ip_ifindex = ifindex; _notify(self, PROP_IP_IFINDEX); } } gboolean -nm_modem_set_data_port(NMModem * self, - NMPlatform * platform, - const char * data_port, +nm_modem_set_data_port(NMModem *self, + NMPlatform *platform, + const char *data_port, NMModemIPMethod ip4_method, NMModemIPMethod ip6_method, guint timeout, - GError ** error) + GError **error) { NMModemPrivate *priv; gboolean is_ppp; @@ -1477,10 +1492,10 @@ nm_modem_set_data_port(NMModem * self, priv->ip6_method = ip6_method; if (is_ppp) { priv->data_port = g_strdup(data_port); - _set_ip_ifindex(self, -1, NULL); + _set_ip_ifindex(self, -1); } else { priv->data_port = NULL; - _set_ip_ifindex(self, ifindex, data_port); + _set_ip_ifindex(self, ifindex); } return TRUE; } @@ -1488,96 +1503,34 @@ nm_modem_set_data_port(NMModem * self, gboolean nm_modem_owns_port(NMModem *self, const char *iface) { - NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); + NMPlatform *platform; + const NMPlatformLink *plink; g_return_val_if_fail(iface != NULL, FALSE); if (NM_MODEM_GET_CLASS(self)->owns_port) return NM_MODEM_GET_CLASS(self)->owns_port(self, iface); - return NM_IN_STRSET(iface, priv->ip_iface, priv->data_port, priv->control_port); -} - -gboolean -nm_modem_get_iid(NMModem *self, NMUtilsIPv6IfaceId *out_iid) -{ - g_return_val_if_fail(NM_IS_MODEM(self), FALSE); - - *out_iid = NM_MODEM_GET_PRIVATE(self)->iid; - return TRUE; -} - -/*****************************************************************************/ - -void -nm_modem_get_route_parameters(NMModem *self, - guint32 *out_ip4_route_table, - guint32 *out_ip4_route_metric, - guint32 *out_ip6_route_table, - guint32 *out_ip6_route_metric) -{ - NMModemPrivate *priv; - - g_return_if_fail(NM_IS_MODEM(self)); - - priv = NM_MODEM_GET_PRIVATE(self); - NM_SET_OUT(out_ip4_route_table, priv->ip4_route_table); - NM_SET_OUT(out_ip4_route_metric, priv->ip4_route_metric); - NM_SET_OUT(out_ip6_route_table, priv->ip6_route_table); - NM_SET_OUT(out_ip6_route_metric, priv->ip6_route_metric); -} - -void -nm_modem_set_route_parameters(NMModem *self, - guint32 ip4_route_table, - guint32 ip4_route_metric, - guint32 ip6_route_table, - guint32 ip6_route_metric) -{ - NMModemPrivate *priv; - - g_return_if_fail(NM_IS_MODEM(self)); - - priv = NM_MODEM_GET_PRIVATE(self); - if (priv->ip4_route_table != ip4_route_table || priv->ip4_route_metric != ip4_route_metric - || priv->ip6_route_table != ip6_route_table || priv->ip6_route_metric != ip6_route_metric) { - priv->ip4_route_table = ip4_route_table; - priv->ip4_route_metric = ip4_route_metric; - priv->ip6_route_table = ip6_route_table; - priv->ip6_route_metric = ip6_route_metric; - - _LOGT("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u", - priv->ip4_route_table, - priv->ip4_route_metric, - priv->ip6_route_table, - priv->ip6_route_metric); - } - - if (priv->ppp_manager) { - nm_ppp_manager_set_route_parameters(priv->ppp_manager, - priv->ip4_route_table, - priv->ip4_route_metric, - priv->ip6_route_table, - priv->ip6_route_metric); - } -} + if (NM_IN_STRSET(iface, priv->data_port, priv->control_port)) + return TRUE; -void -nm_modem_set_route_parameters_from_device(NMModem *self, NMDevice *device) -{ - g_return_if_fail(NM_IS_DEVICE(device)); + /* FIXME(parent-child-relationship): the whole notion of "owns-port" is wrong. + * When we have a name (iface) it must be always clear what this name is (which + * domain). Mixing data_port, control_port and devlink names is wrong. Looking + * up devlinks by name is also wrong (use ifindex). */ + if (priv->ip_ifindex > 0 && (platform = _get_platform(self)) + && (plink = nm_platform_link_get(platform, priv->ip_ifindex)) + && nm_streq(iface, plink->name)) + return TRUE; - nm_modem_set_route_parameters(self, - nm_device_get_route_table(device, AF_INET), - nm_device_get_route_metric(device, AF_INET), - nm_device_get_route_table(device, AF_INET6), - nm_device_get_route_metric(device, AF_INET6)); + return FALSE; } /*****************************************************************************/ void -nm_modem_get_capabilities(NMModem * self, +nm_modem_get_capabilities(NMModem *self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps) { @@ -1593,9 +1546,10 @@ _nm_modem_set_operator_code(NMModem *self, const char *operator_code) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - if (g_strcmp0(priv->operator_code, operator_code) != 0) { + if (!nm_streq0(priv->operator_code, operator_code)) { g_free(priv->operator_code); priv->operator_code = g_strdup(operator_code); + _LOGD("signal: operator-code changed: %s%s%s", NM_PRINT_FMT_QUOTE_STRING(operator_code)); _notify(self, PROP_OPERATOR_CODE); } } @@ -1605,9 +1559,10 @@ _nm_modem_set_apn(NMModem *self, const char *apn) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); - if (g_strcmp0(priv->apn, apn) != 0) { + if (!nm_streq0(priv->apn, apn)) { g_free(priv->apn); priv->apn = g_strdup(apn); + _LOGD("signal: apn changed: %s%s%s", NM_PRINT_FMT_QUOTE_STRING(apn)); _notify(self, PROP_APN); } } @@ -1615,7 +1570,7 @@ _nm_modem_set_apn(NMModem *self, const char *apn) static void get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMModem * self = NM_MODEM(object); + NMModem *self = NM_MODEM(object); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(self); switch (prop_id) { @@ -1665,7 +1620,7 @@ static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(object); - const char * s; + const char *s; switch (prop_id) { case PROP_PATH: @@ -1726,11 +1681,7 @@ nm_modem_init(NMModem *self) self->_priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_MODEM, NMModemPrivate); priv = self->_priv; - priv->ip_ifindex = -1; - priv->ip4_route_table = RT_TABLE_MAIN; - priv->ip4_route_metric = 700; - priv->ip6_route_table = RT_TABLE_MAIN; - priv->ip6_route_metric = 700; + priv->ip_ifindex = -1; } static void @@ -1752,7 +1703,8 @@ dispose(GObject *object) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(object); - g_clear_object(&priv->act_request); + g_clear_object(&priv->act_req); + g_clear_object(&priv->device); G_OBJECT_CLASS(nm_modem_parent_class)->dispose(object); } @@ -1767,7 +1719,6 @@ finalize(GObject *object) g_free(priv->driver); g_free(priv->control_port); g_free(priv->data_port); - g_free(priv->ip_iface); g_free(priv->device_id); g_free(priv->sim_id); g_free(priv->sim_operator_id); @@ -1790,9 +1741,8 @@ nm_modem_class_init(NMModemClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; - klass->modem_act_stage1_prepare = modem_act_stage1_prepare; - klass->stage3_ip6_config_request = stage3_ip6_config_request; - klass->deactivate_cleanup = deactivate_cleanup; + klass->modem_act_stage1_prepare = modem_act_stage1_prepare; + klass->deactivate_cleanup = deactivate_cleanup; obj_properties[PROP_UID] = g_param_spec_string(NM_MODEM_UID, @@ -1904,43 +1854,28 @@ nm_modem_class_init(NMModemClass *klass) 1, G_TYPE_UINT); - signals[IP4_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP4_CONFIG_RESULT, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 2, - G_TYPE_OBJECT, - G_TYPE_POINTER); - - /** - * NMModem::ip6-config-result: - * @modem: the #NMModem on which the signal is emitted - * @config: the #NMIP6Config to apply to the modem's data port - * @do_slaac: %TRUE if IPv6 SLAAC should be started - * @error: a #GError if any error occurred during IP configuration - * - * This signal is emitted when IPv6 configuration has completed or failed. - * If @error is set the configuration failed. If @config is set, then + /* + * This signal is emitted when IP configuration has completed or failed. + * If @error is set the configuration failed. If @l3cd is set, then * the details should be applied to the data port before any further - * configuration (like SLAAC) is done. @do_slaac indicates whether SLAAC - * should be started after applying @config to the data port. + * configuration (like SLAAC) is done. @do_auto indicates whether DHCPv4/SLAAC + * should be started after applying @l3cd to the data port. */ - signals[IP6_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP6_CONFIG_RESULT, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 3, - G_TYPE_OBJECT, - G_TYPE_BOOLEAN, - G_TYPE_POINTER); + signals[NEW_CONFIG] = g_signal_new(NM_MODEM_NEW_CONFIG, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 6, + G_TYPE_INT, /* int addr_family */ + G_TYPE_POINTER, /* const NML3ConfigData *l3cd */ + G_TYPE_BOOLEAN, /* gboolean do_auto */ + G_TYPE_POINTER, /* const NMUtilsIPv6IfaceId *iid */ + G_TYPE_INT, /* NMDeviceStateReason failure_reason */ + G_TYPE_POINTER); /* GError *error */ signals[PREPARE_RESULT] = g_signal_new(NM_MODEM_PREPARE_RESULT, G_OBJECT_CLASS_TYPE(object_class), diff --git a/src/core/devices/wwan/nm-modem.h b/src/core/devices/wwan/nm-modem.h index 4bc81ff8..ca541073 100644 --- a/src/core/devices/wwan/nm-modem.h +++ b/src/core/devices/wwan/nm-modem.h @@ -32,15 +32,14 @@ #define NM_MODEM_APN "apn" /* Signals */ -#define NM_MODEM_PPP_STATS "ppp-stats" -#define NM_MODEM_PPP_FAILED "ppp-failed" -#define NM_MODEM_PREPARE_RESULT "prepare-result" -#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result" -#define NM_MODEM_IP6_CONFIG_RESULT "ip6-config-result" -#define NM_MODEM_AUTH_REQUESTED "auth-requested" -#define NM_MODEM_AUTH_RESULT "auth-result" -#define NM_MODEM_REMOVED "removed" -#define NM_MODEM_STATE_CHANGED "state-changed" +#define NM_MODEM_PPP_STATS "ppp-stats" +#define NM_MODEM_PPP_FAILED "ppp-failed" +#define NM_MODEM_PREPARE_RESULT "prepare-result" +#define NM_MODEM_NEW_CONFIG "new-config" +#define NM_MODEM_AUTH_REQUESTED "auth-requested" +#define NM_MODEM_AUTH_RESULT "auth-result" +#define NM_MODEM_REMOVED "removed" +#define NM_MODEM_STATE_CHANGED "state-changed" typedef enum { NM_MODEM_IP_METHOD_UNKNOWN = 0, @@ -101,44 +100,36 @@ typedef void (*_NMModemDisconnectCallback)(NMModem *modem, GError *error, gpoint typedef struct { GObjectClass parent; - void (*get_capabilities)(NMModem * self, + void (*get_capabilities)(NMModem *self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps); - gboolean (*get_user_pass)(NMModem * modem, + gboolean (*get_user_pass)(NMModem *modem, NMConnection *connection, - const char ** user, - const char ** pass); + const char **user, + const char **pass); - gboolean (*check_connection_compatible_with_modem)(NMModem * modem, + gboolean (*check_connection_compatible_with_modem)(NMModem *modem, NMConnection *connection, - GError ** error); + GError **error); - gboolean (*complete_connection)(NMModem * modem, - const char * iface, - NMConnection * connection, + gboolean (*complete_connection)(NMModem *modem, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error); + GError **error); - NMActStageReturn (*modem_act_stage1_prepare)(NMModem * modem, - NMConnection * connection, + NMActStageReturn (*modem_act_stage1_prepare)(NMModem *modem, + NMConnection *connection, NMDeviceStateReason *out_failure_reason); - NMActStageReturn (*static_stage3_ip4_config_start)(NMModem * self, - NMActRequest * req, - NMDeviceStateReason *out_failure_reason); - - /* Request the IP6 config; when the config returns the modem - * subclass should emit the ip6_config_result signal. - */ - NMActStageReturn (*stage3_ip6_config_request)(NMModem * self, - NMDeviceStateReason *out_failure_reason); + void (*stage3_ip_config_start)(NMModem *self, int addr_family, NMModemIPMethod method); void (*set_mm_enabled)(NMModem *self, gboolean enabled); - void (*disconnect)(NMModem * self, + void (*disconnect)(NMModem *self, gboolean warn, - GCancellable * cancellable, + GCancellable *cancellable, _NMModemDisconnectCallback callback, gpointer user_data); @@ -161,65 +152,43 @@ const char *nm_modem_get_driver(NMModem *modem); const char *nm_modem_get_device_id(NMModem *modem); const char *nm_modem_get_sim_id(NMModem *modem); const char *nm_modem_get_sim_operator_id(NMModem *modem); -gboolean nm_modem_get_iid(NMModem *modem, NMUtilsIPv6IfaceId *out_iid); const char *nm_modem_get_operator_code(NMModem *modem); const char *nm_modem_get_apn(NMModem *modem); -gboolean nm_modem_set_data_port(NMModem * self, - NMPlatform * platform, - const char * data_port, +gboolean nm_modem_set_data_port(NMModem *self, + NMPlatform *platform, + const char *data_port, NMModemIPMethod ip4_method, NMModemIPMethod ip6_method, guint timeout, - GError ** error); + GError **error); gboolean nm_modem_owns_port(NMModem *modem, const char *iface); -void nm_modem_get_capabilities(NMModem * self, +void nm_modem_get_capabilities(NMModem *self, NMDeviceModemCapabilities *modem_caps, NMDeviceModemCapabilities *current_caps); gboolean nm_modem_check_connection_compatible(NMModem *self, NMConnection *connection, GError **error); -gboolean nm_modem_complete_connection(NMModem * self, - const char * iface, - NMConnection * connection, +gboolean nm_modem_complete_connection(NMModem *self, + const char *iface, + NMConnection *connection, NMConnection *const *existing_connections, - GError ** error); - -void nm_modem_get_route_parameters(NMModem *self, - guint32 *out_ip4_route_table, - guint32 *out_ip4_route_metric, - guint32 *out_ip6_route_table, - guint32 *out_ip6_route_metric); - -void nm_modem_set_route_parameters(NMModem *self, - guint32 ip4_route_table, - guint32 ip4_route_metric, - guint32 ip6_route_table, - guint32 ip6_route_metric); - -void nm_modem_set_route_parameters_from_device(NMModem *modem, NMDevice *device); + GError **error); -NMActStageReturn nm_modem_act_stage1_prepare(NMModem * modem, - NMActRequest * req, +NMActStageReturn nm_modem_act_stage1_prepare(NMModem *modem, + NMActRequest *req, NMDeviceStateReason *out_failure_reason); -void nm_modem_act_stage2_config(NMModem *modem); +NMActStageReturn nm_modem_act_stage2_config(NMModem *self, + NMDevice *device, + NMDeviceStateReason *out_failure_reason); -NMActStageReturn nm_modem_stage3_ip4_config_start(NMModem * modem, - NMDevice * device, - gboolean * out_autoip4, - NMDeviceStateReason *out_failure_reason); +gboolean nm_modem_stage3_ip_config_start(NMModem *self, int addr_family, NMDevice *device); -NMActStageReturn nm_modem_stage3_ip6_config_start(NMModem * modem, - NMDevice * device, - NMDeviceStateReason *out_failure_reason); - -void nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config); - -void nm_modem_get_secrets(NMModem * modem, +void nm_modem_get_secrets(NMModem *modem, const char *setting_name, gboolean request_new, const char *hint); @@ -228,9 +197,9 @@ void nm_modem_deactivate(NMModem *modem, NMDevice *device); typedef void (*NMModemDeactivateCallback)(NMModem *self, GError *error, gpointer user_data); -void nm_modem_deactivate_async(NMModem * self, - NMDevice * device, - GCancellable * cancellable, +void nm_modem_deactivate_async(NMModem *self, + NMDevice *device, + GCancellable *cancellable, NMModemDeactivateCallback callback, gpointer user_data); @@ -242,13 +211,15 @@ void nm_modem_set_mm_enabled(NMModem *self, gboolean enabled); NMModemState nm_modem_get_state(NMModem *self); void nm_modem_set_state(NMModem *self, NMModemState new_state, const char *reason); void nm_modem_set_prev_state(NMModem *self, const char *reason); -const char * nm_modem_state_to_string(NMModemState state); +const char *nm_modem_state_to_string(NMModemState state); NMModemIPType nm_modem_get_supported_ip_types(NMModem *self); /* For the modem-manager only */ void nm_modem_emit_removed(NMModem *self); +void nm_modem_emit_auth_requested(NMModem *self); + void nm_modem_emit_prepare_result(NMModem *self, gboolean success, NMDeviceStateReason reason); void nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason); @@ -256,7 +227,23 @@ void nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason); GArray *nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError **error); /* For subclasses */ -void nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error); + +void nm_modem_emit_signal_new_config(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_slaac, + const NMUtilsIPv6IfaceId *iid, + NMDeviceStateReason failure_reason, + GError *error); +void nm_modem_emit_signal_new_config_success(NMModem *self, + int addr_family, + const NML3ConfigData *l3cd, + gboolean do_auto, + const NMUtilsIPv6IfaceId *iid); +void nm_modem_emit_signal_new_config_failure(NMModem *self, + int addr_family, + NMDeviceStateReason failure_reason, + GError *error); const char *nm_modem_ip_type_to_string(NMModemIPType ip_type); diff --git a/src/core/devices/wwan/nm-service-providers.c b/src/core/devices/wwan/nm-service-providers.c index 89add6c5..83f21565 100644 --- a/src/core/devices/wwan/nm-service-providers.c +++ b/src/core/devices/wwan/nm-service-providers.c @@ -22,33 +22,33 @@ typedef enum { } ParseContextState; typedef struct { - char * mccmnc; + char *mccmnc; NMServiceProvidersGsmApnCallback callback; gpointer user_data; - GCancellable * cancellable; - GMarkupParseContext * ctx; + GCancellable *cancellable; + GMarkupParseContext *ctx; char buffer[4096]; - char * text_buffer; + char *text_buffer; ParseContextState state; gboolean mccmnc_matched; gboolean found_internet_apn; - char * apn; - char * username; - char * password; - char * gateway; - char * auth_method; - GSList * dns; + char *apn; + char *username; + char *password; + char *gateway; + char *auth_method; + GSList *dns; } ParseContext; /*****************************************************************************/ static void parser_toplevel_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { int i; @@ -72,9 +72,9 @@ parser_toplevel_start(ParseContext *parse_context, static void parser_country_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { if (strcmp(name, "provider") == 0) parse_context->state = PARSER_PROVIDER; @@ -82,9 +82,9 @@ parser_country_start(ParseContext *parse_context, static void parser_provider_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { parse_context->mccmnc_matched = FALSE; if (strcmp(name, "gsm") == 0) @@ -95,9 +95,9 @@ parser_provider_start(ParseContext *parse_context, static void parser_gsm_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { int i; @@ -140,9 +140,9 @@ parser_gsm_start(ParseContext *parse_context, static void parser_gsm_apn_start(ParseContext *parse_context, - const char * name, - const char ** attribute_names, - const char ** attribute_values) + const char *name, + const char **attribute_names, + const char **attribute_values) { int i; @@ -167,11 +167,11 @@ parser_gsm_apn_start(ParseContext *parse_context, static void parser_start_element(GMarkupParseContext *context, - const char * element_name, - const char ** attribute_names, - const char ** attribute_values, + const char *element_name, + const char **attribute_names, + const char **attribute_values, gpointer user_data, - GError ** error) + GError **error) { ParseContext *parse_context = user_data; @@ -265,9 +265,9 @@ parser_cdma_end(ParseContext *parse_context, const char *name) static void parser_end_element(GMarkupParseContext *context, - const char * element_name, + const char *element_name, gpointer user_data, - GError ** error) + GError **error) { ParseContext *parse_context = user_data; @@ -298,10 +298,10 @@ parser_end_element(GMarkupParseContext *context, static void parser_text(GMarkupParseContext *context, - const char * text, + const char *text, gsize text_len, gpointer user_data, - GError ** error) + GError **error) { ParseContext *parse_context = user_data; @@ -360,7 +360,7 @@ stream_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) GInputStream *stream = G_INPUT_STREAM(source_object); ParseContext *parse_context = user_data; gssize len; - GError * error = NULL; + GError *error = NULL; len = g_input_stream_read_finish(stream, res, &error); if (len == -1) { @@ -411,9 +411,9 @@ read_next_chunk(GInputStream *stream, ParseContext *parse_context) static void file_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - GFile * file = G_FILE(source_object); - ParseContext * parse_context = user_data; - GFileInputStream *stream; + GFile *file = G_FILE(source_object); + ParseContext *parse_context = user_data; + GFileInputStream *stream; gs_free_error GError *error = NULL; stream = g_file_read_finish(file, res, &error); @@ -431,13 +431,13 @@ file_read_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) /*****************************************************************************/ void -nm_service_providers_find_gsm_apn(const char * service_providers, - const char * mccmnc, - GCancellable * cancellable, +nm_service_providers_find_gsm_apn(const char *service_providers, + const char *mccmnc, + GCancellable *cancellable, NMServiceProvidersGsmApnCallback callback, gpointer user_data) { - GFile * file; + GFile *file; ParseContext *parse_context; parse_context = g_slice_new0(ParseContext); diff --git a/src/core/devices/wwan/nm-service-providers.h b/src/core/devices/wwan/nm-service-providers.h index 959f660a..cf90ef1e 100644 --- a/src/core/devices/wwan/nm-service-providers.h +++ b/src/core/devices/wwan/nm-service-providers.h @@ -6,18 +6,18 @@ #ifndef __NETWORKMANAGER_SERVICE_PROVIDERS_H__ #define __NETWORKMANAGER_SERVICE_PROVIDERS_H__ -typedef void (*NMServiceProvidersGsmApnCallback)(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +typedef void (*NMServiceProvidersGsmApnCallback)(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data); -void nm_service_providers_find_gsm_apn(const char * service_providers, - const char * mccmnc, - GCancellable * cancellable, +void nm_service_providers_find_gsm_apn(const char *service_providers, + const char *mccmnc, + GCancellable *cancellable, NMServiceProvidersGsmApnCallback callback, gpointer user_data); diff --git a/src/core/devices/wwan/nm-wwan-factory.c b/src/core/devices/wwan/nm-wwan-factory.c index 0d802ae1..169407c7 100644 --- a/src/core/devices/wwan/nm-wwan-factory.c +++ b/src/core/devices/wwan/nm-wwan-factory.c @@ -52,7 +52,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES(NM_DEVICE_FACTORY_DECLARE_LINK_TYPES( NM_SETTING_CDMA_SETTING_NAME)) G_MODULE_EXPORT NMDeviceFactory * - nm_device_factory_create(GError **error) +nm_device_factory_create(GError **error) { return g_object_new(NM_TYPE_WWAN_FACTORY, NULL); } @@ -62,9 +62,9 @@ G_MODULE_EXPORT NMDeviceFactory * static void modem_added_cb(NMModemManager *manager, NMModem *modem, gpointer user_data) { - NMWwanFactory * self = NM_WWAN_FACTORY(user_data); + NMWwanFactory *self = NM_WWAN_FACTORY(user_data); gs_unref_object NMDevice *device = NULL; - const char * driver; + const char *driver; if (nm_modem_is_claimed(modem)) return; @@ -89,11 +89,11 @@ modem_added_cb(NMModemManager *manager, NMModem *modem, gpointer user_data) } static NMDevice * -create_device(NMDeviceFactory * factory, - const char * iface, +create_device(NMDeviceFactory *factory, + const char *iface, const NMPlatformLink *plink, - NMConnection * connection, - gboolean * out_ignore) + NMConnection *connection, + gboolean *out_ignore) { g_return_val_if_fail(plink, NULL); g_return_val_if_fail(plink->type == NM_LINK_TYPE_WWAN_NET, NULL); @@ -104,7 +104,7 @@ create_device(NMDeviceFactory * factory, static void start(NMDeviceFactory *factory) { - NMWwanFactory * self = NM_WWAN_FACTORY(factory); + NMWwanFactory *self = NM_WWAN_FACTORY(factory); NMWwanFactoryPrivate *priv = NM_WWAN_FACTORY_GET_PRIVATE(self); priv->mm = g_object_ref(nm_modem_manager_get()); @@ -121,7 +121,7 @@ nm_wwan_factory_init(NMWwanFactory *self) static void dispose(GObject *object) { - NMWwanFactory * self = NM_WWAN_FACTORY(object); + NMWwanFactory *self = NM_WWAN_FACTORY(object); NMWwanFactoryPrivate *priv = NM_WWAN_FACTORY_GET_PRIVATE(self); if (priv->mm) @@ -135,7 +135,7 @@ dispose(GObject *object) static void nm_wwan_factory_class_init(NMWwanFactoryClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); NMDeviceFactoryClass *factory_class = NM_DEVICE_FACTORY_CLASS(klass); object_class->dispose = dispose; diff --git a/src/core/devices/wwan/tests/test-service-providers.c b/src/core/devices/wwan/tests/test-service-providers.c index f95cccf8..e808b391 100644 --- a/src/core/devices/wwan/tests/test-service-providers.c +++ b/src/core/devices/wwan/tests/test-service-providers.c @@ -10,13 +10,13 @@ #include "nm-test-utils-core.h" static void -test_positive_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +test_positive_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { GMainLoop *loop = user_data; @@ -55,13 +55,13 @@ test_positive(void) /*****************************************************************************/ static void -test_negative_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +test_negative_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { GMainLoop *loop = user_data; @@ -88,13 +88,13 @@ test_negative(void) /*****************************************************************************/ static void -test_nonexistent_cb(const char * apn, - const char * username, - const char * password, - const char * gateway, - const char * auth_method, +test_nonexistent_cb(const char *apn, + const char *username, + const char *password, + const char *gateway, + const char *auth_method, const GSList *dns, - GError * error, + GError *error, gpointer user_data) { GMainLoop *loop = user_data; |