From 8bdf070ff046f482f6eb5e2b15ebc216f5d1e3da Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Wed, 12 Feb 2025 13:46:50 +0100 Subject: New upstream version 1.51.90 --- src/core/devices/adsl/nm-device-adsl.c | 5 +- src/core/devices/bluetooth/nm-bluez-manager.c | 10 +- src/core/devices/bluetooth/nm-bluez5-dun.c | 4 +- src/core/devices/bluetooth/nm-device-bt.c | 3 +- src/core/devices/nm-device-6lowpan.c | 29 +- src/core/devices/nm-device-bond.c | 7 +- src/core/devices/nm-device-bridge.c | 33 +- src/core/devices/nm-device-dummy.c | 16 +- src/core/devices/nm-device-ethernet.c | 8 +- src/core/devices/nm-device-factory.c | 3 +- src/core/devices/nm-device-factory.h | 12 +- src/core/devices/nm-device-infiniband.c | 26 +- src/core/devices/nm-device-ip-tunnel.c | 31 +- src/core/devices/nm-device-ipvlan.c | 467 ++++++++++++++++ src/core/devices/nm-device-ipvlan.h | 31 ++ src/core/devices/nm-device-loopback.c | 16 +- src/core/devices/nm-device-macsec.c | 33 +- src/core/devices/nm-device-macvlan.c | 41 +- src/core/devices/nm-device-ppp.c | 19 +- src/core/devices/nm-device-private.h | 4 +- src/core/devices/nm-device-tun.c | 3 +- src/core/devices/nm-device-utils.c | 2 +- src/core/devices/nm-device-vlan.c | 37 +- src/core/devices/nm-device-vrf.c | 5 +- src/core/devices/nm-device-vxlan.c | 29 +- src/core/devices/nm-device-wireguard.c | 20 +- src/core/devices/nm-device-wpan.c | 3 +- src/core/devices/nm-device.c | 712 +++++++++++++++++++------ src/core/devices/nm-lldp-listener.c | 10 +- src/core/devices/ovs/nm-device-ovs-interface.c | 2 +- src/core/devices/ovs/nm-device-ovs-port.c | 4 +- src/core/devices/ovs/nm-ovsdb.c | 22 +- src/core/devices/team/nm-device-team.c | 3 +- src/core/devices/wifi/nm-device-iwd-p2p.c | 3 +- src/core/devices/wifi/nm-device-iwd.c | 15 +- src/core/devices/wifi/nm-device-olpc-mesh.c | 3 +- src/core/devices/wifi/nm-device-wifi-p2p.c | 3 +- src/core/devices/wifi/nm-device-wifi.c | 5 +- src/core/devices/wifi/nm-wifi-utils.c | 16 +- src/core/devices/wwan/nm-modem-broadband.c | 41 +- src/core/devices/wwan/nm-modem-ofono.c | 4 +- src/core/devices/wwan/nm-modem.c | 2 +- 42 files changed, 1262 insertions(+), 480 deletions(-) create mode 100644 src/core/devices/nm-device-ipvlan.c create mode 100644 src/core/devices/nm-device-ipvlan.h (limited to 'src/core/devices') diff --git a/src/core/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c index ba605077..a6dc6326 100644 --- a/src/core/devices/adsl/nm-device-adsl.c +++ b/src/core/devices/adsl/nm-device-adsl.c @@ -117,8 +117,7 @@ complete_connection(NMDevice *device, NULL, _("ADSL connection"), NULL, - NULL, - FALSE); /* No IPv6 yet by default */ + NULL); return TRUE; } @@ -494,7 +493,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) _LOGD(LOGD_ADSL, "starting PPPoA"); } - priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){ + priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig) { .netns = nm_device_get_netns(device), .parent_iface = ppp_iface, .callback = _ppp_mgr_callback, diff --git a/src/core/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index ac26ede8..3088cd6f 100644 --- a/src/core/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -334,7 +334,7 @@ _bz_dbus_obj_new(NMBluezManager *self, const char *object_path) l = strlen(object_path) + 1; bzobj = g_malloc(sizeof(BzDBusObj) + l); - *bzobj = (BzDBusObj){ + *bzobj = (BzDBusObj) { .object_path = bzobj->_object_path_intern, .self = self, .x_network_server.lst = C_LIST_INIT(bzobj->x_network_server.lst), @@ -751,7 +751,7 @@ _conn_data_head_new(NMBluetoothCapabilities bt_type, const char *bdaddr) l = strlen(bdaddr) + 1; cdata_hd = g_malloc(sizeof(ConnDataHead) + l); - *cdata_hd = (ConnDataHead){ + *cdata_hd = (ConnDataHead) { .bdaddr = cdata_hd->bdaddr_data, .lst_head = C_LIST_INIT(cdata_hd->lst_head), .bt_type = bt_type, @@ -1143,7 +1143,7 @@ _network_server_vt_register_bridge(const NMBtVTableNetworkServer *vtable, bzobj->d_adapter.address); r_req_data = g_slice_new(NetworkServerRegisterReqData); - *r_req_data = (NetworkServerRegisterReqData){ + *r_req_data = (NetworkServerRegisterReqData) { .int_cancellable = g_cancellable_new(), .ext_cancellable = g_object_ref(cancellable), .callback = callback, @@ -2749,7 +2749,7 @@ nm_bluez_manager_connect(NMBluezManager *self, } c_req_data = g_slice_new(DeviceConnectReqData); - *c_req_data = (DeviceConnectReqData){ + *c_req_data = (DeviceConnectReqData) { .int_cancellable = g_steal_pointer(&int_cancellable), .ext_cancellable = g_object_ref(cancellable), .callback = callback, @@ -2814,7 +2814,7 @@ nm_bluez_manager_init(NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE(self); - priv->vtable_network_server = (NMBtVTableNetworkServer){ + priv->vtable_network_server = (NMBtVTableNetworkServer) { .is_available = _network_server_vt_is_available, .register_bridge = _network_server_vt_register_bridge, .unregister_bridge = _network_server_vt_unregister_bridge, diff --git a/src/core/devices/bluetooth/nm-bluez5-dun.c b/src/core/devices/bluetooth/nm-bluez5-dun.c index 426bab0c..08d37c27 100644 --- a/src/core/devices/bluetooth/nm-bluez5-dun.c +++ b/src/core/devices/bluetooth/nm-bluez5-dun.c @@ -683,7 +683,7 @@ nm_bluez5_dun_connect(const char *adapter, dst_l = strlen(remote) + 1; cdat = g_slice_new(ConnectData); - *cdat = (ConnectData){ + *cdat = (ConnectData) { .callback = callback, .callback_user_data = callback_user_data, .cancellable = g_object_ref(cancellable), @@ -691,7 +691,7 @@ nm_bluez5_dun_connect(const char *adapter, }; context = g_malloc(sizeof(NMBluez5DunContext) + src_l + dst_l); - *context = (NMBluez5DunContext){ + *context = (NMBluez5DunContext) { .cdat = cdat, .notify_tty_hangup_cb = notify_tty_hangup_cb, .notify_tty_hangup_user_data = notify_tty_hangup_user_data, diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c index ce110aa0..4406bcf4 100644 --- a/src/core/devices/bluetooth/nm-device-bt.c +++ b/src/core/devices/bluetooth/nm-device-bt.c @@ -404,8 +404,7 @@ complete_connection(NMDevice *device, preferred, fallback_prefix, NULL, - NULL, - is_dun ? FALSE : TRUE); /* No IPv6 yet for DUN */ + NULL); setting_bdaddr = nm_setting_bluetooth_get_bdaddr(s_bt); if (setting_bdaddr) { diff --git a/src/core/devices/nm-device-6lowpan.c b/src/core/devices/nm-device-6lowpan.c index 78ec634c..3dabcb9b 100644 --- a/src/core/devices/nm-device-6lowpan.c +++ b/src/core/devices/nm-device-6lowpan.c @@ -161,8 +161,7 @@ complete_connection(NMDevice *device, NULL, _("6LOWPAN connection"), NULL, - NULL, - TRUE); + NULL); s_6lowpan = NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN)); if (!s_6lowpan) { @@ -276,27 +275,10 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_6LOWPAN_SETTING_NAME), NULL); s_6lowpan = NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN)); - g_assert(s_6lowpan); - - return nm_setting_6lowpan_get_parent(s_6lowpan); -} - -static char * -get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) -{ - NMSetting6Lowpan *s_6lowpan; - const char *ifname; - - g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_6LOWPAN_SETTING_NAME), NULL); - - s_6lowpan = NM_SETTING_6LOWPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_6LOWPAN)); - g_assert(s_6lowpan); - - if (!parent_iface) + if (s_6lowpan) + return nm_setting_6lowpan_get_parent(s_6lowpan); + else return NULL; - - ifname = nm_connection_get_interface_name(connection); - return g_strdup(ifname); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( @@ -306,5 +288,4 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL( NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_6LOWPAN) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_6LOWPAN_SETTING_NAME), factory_class->create_device = create_device; - factory_class->get_connection_parent = get_connection_parent; - factory_class->get_connection_iface = get_connection_iface;); + factory_class->get_connection_parent = get_connection_parent;); diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 3ab17aff..53b32466 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -94,8 +94,7 @@ complete_connection(NMDevice *device, NULL, _("Bond connection"), "bond", - NULL, - TRUE); + NULL); _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BOND); @@ -436,7 +435,7 @@ _platform_lnk_bond_init_from_setting(NMSettingBond *s_bond, NMPlatformLnkBond *p #define _v_u32(s_bond, opt) _nm_setting_bond_opt_value_as_u32((s_bond), (opt)) #define _v_intbool(s_bond, opt) _nm_setting_bond_opt_value_as_intbool((s_bond), (opt)) - *props = (NMPlatformLnkBond){ + *props = (NMPlatformLnkBond) { .mode = _v_fcn(_nm_setting_bond_mode_from_string, s_bond, NM_SETTING_BOND_OPTION_MODE), .primary = _setting_bond_primary_opt_as_ifindex(s_bond), .miimon = _v_u32(s_bond, NM_SETTING_BOND_OPTION_MIIMON), @@ -681,7 +680,7 @@ commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_ nm_platform_link_change(nm_device_get_platform(port), nm_device_get_ifindex(port), NULL, - &((NMPlatformLinkBondPort){ + &((NMPlatformLinkBondPort) { .queue_id = s_port ? nm_setting_bond_port_get_queue_id(s_port) : NM_BOND_PORT_QUEUE_ID_DEF, .prio = prio_has ? prio : 0, diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index a237c0b7..7c34fde0 100644 --- a/src/core/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -164,8 +164,7 @@ complete_connection(NMDevice *device, NULL, _("Bridge connection"), "bridge", - NULL, - TRUE); + NULL); _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BRIDGE); @@ -439,7 +438,7 @@ setting_vlans_to_platform(GPtrArray *array, guint *out_len) nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); - arr[i] = (NMPlatformBridgeVlan){ + arr[i] = (NMPlatformBridgeVlan) { .vid_start = vid_start, .vid_end = vid_end, .pvid = nm_bridge_vlan_is_pvid(vlan), @@ -468,7 +467,7 @@ commit_port_options(NMDevice *device, NMSettingBridgePort *setting) nm_device_get_ifindex(device), NULL, NULL, - &((NMPlatformLinkBridgePort){ + &((NMPlatformLinkBridgePort) { .path_cost = path_cost, .priority = priority, .hairpin = nm_setting_bridge_port_get_hairpin_mode(setting), @@ -660,10 +659,10 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge, gboolean is nm_platform_link_set_bridge_info( plat, ifindex, - &((NMPlatformLinkSetBridgeInfoData){.vlan_filtering_has = TRUE, - .vlan_filtering_val = FALSE, - .vlan_default_pvid_has = TRUE, - .vlan_default_pvid_val = 1})); + &((NMPlatformLinkSetBridgeInfoData) {.vlan_filtering_has = TRUE, + .vlan_filtering_val = FALSE, + .vlan_default_pvid_has = TRUE, + .vlan_default_pvid_val = 1})); nm_platform_link_set_bridge_vlans(plat, ifindex, FALSE, NULL, 0); return TRUE; } @@ -690,10 +689,10 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge, gboolean is nm_platform_link_set_bridge_info( plat, ifindex, - &((NMPlatformLinkSetBridgeInfoData){.vlan_filtering_has = TRUE, - .vlan_filtering_val = FALSE, - .vlan_default_pvid_has = TRUE, - .vlan_default_pvid_val = 0})); + &((NMPlatformLinkSetBridgeInfoData) {.vlan_filtering_has = TRUE, + .vlan_filtering_val = FALSE, + .vlan_default_pvid_has = TRUE, + .vlan_default_pvid_val = 0})); /* Clear all existing VLANs */ if (!nm_platform_link_set_bridge_vlans(plat, ifindex, FALSE, NULL, 0)) @@ -706,8 +705,8 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge, gboolean is nm_platform_link_set_bridge_info( plat, ifindex, - &((NMPlatformLinkSetBridgeInfoData){.vlan_default_pvid_has = TRUE, - .vlan_default_pvid_val = pvid})); + &((NMPlatformLinkSetBridgeInfoData) {.vlan_default_pvid_has = TRUE, + .vlan_default_pvid_val = pvid})); } } @@ -721,7 +720,7 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge, gboolean is nm_platform_link_set_bridge_info(plat, ifindex, - &((NMPlatformLinkSetBridgeInfoData){ + &((NMPlatformLinkSetBridgeInfoData) { .vlan_filtering_has = TRUE, .vlan_filtering_val = TRUE, })); @@ -757,7 +756,7 @@ merge_bridge_vlan_default_pvid(NMPlatformBridgeVlan *vlans, guint *num_vlans, gu * Set the PVID flag only if the port didn't have one. */ vlans = g_realloc_n(vlans, *num_vlans + 1, sizeof(NMPlatformBridgeVlan)); (*num_vlans)++; - vlans[*num_vlans - 1] = (NMPlatformBridgeVlan){ + vlans[*num_vlans - 1] = (NMPlatformBridgeVlan) { .vid_start = default_pvid, .vid_end = default_pvid, .untagged = TRUE, @@ -847,7 +846,7 @@ nm_device_reapply_bridge_port_vlans(NMDevice *device) static void _platform_lnk_bridge_init_from_setting(NMSettingBridge *s_bridge, NMPlatformLnkBridge *props) { - *props = (NMPlatformLnkBridge){ + *props = (NMPlatformLnkBridge) { .forward_delay = _DEFAULT_IF_ZERO(nm_setting_bridge_get_forward_delay(s_bridge) * 100u, NM_BRIDGE_FORWARD_DELAY_DEF_SYS), .hello_time = _DEFAULT_IF_ZERO(nm_setting_bridge_get_hello_time(s_bridge) * 100u, diff --git a/src/core/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c index b7c4106a..1bc5447f 100644 --- a/src/core/devices/nm-device-dummy.c +++ b/src/core/devices/nm-device-dummy.c @@ -48,14 +48,14 @@ complete_connection(NMDevice *device, NMConnection *const *existing_connections, GError **error) { - nm_utils_complete_generic_with_params(nm_device_get_platform(device), - connection, - NM_SETTING_DUMMY_SETTING_NAME, - existing_connections, - NULL, - _("Dummy connection"), - NULL, - nm_device_get_ip_iface(device)); + nm_utils_complete_generic(nm_device_get_platform(device), + connection, + NM_SETTING_DUMMY_SETTING_NAME, + existing_connections, + NULL, + _("Dummy connection"), + NULL, + nm_device_get_ip_iface(device)); _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_DUMMY); diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 16992524..4034fdaa 100644 --- a/src/core/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -1451,7 +1451,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); priv->ppp_data.ppp_mgr = - nm_ppp_mgr_start(&((const NMPppMgrConfig){ + nm_ppp_mgr_start(&((const NMPppMgrConfig) { .netns = nm_device_get_netns(device), .parent_iface = nm_device_get_iface(device), .callback = _ppp_mgr_callback, @@ -1640,8 +1640,7 @@ complete_connection(NMDevice *device, NULL, _("Veth connection"), "veth", - NULL, - TRUE); + NULL); s_veth = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_VETH); @@ -1698,8 +1697,7 @@ complete_connection(NMDevice *device, NULL, s_pppoe ? _("PPPoE connection") : _("Wired connection"), NULL, - nm_setting_wired_get_mac_address(s_wired) ? NULL : nm_device_get_iface(device), - s_pppoe ? FALSE : TRUE); /* No IPv6 by default yet for PPPoE */ + nm_setting_wired_get_mac_address(s_wired) ? NULL : nm_device_get_iface(device)); return TRUE; } diff --git a/src/core/devices/nm-device-factory.c b/src/core/devices/nm-device-factory.c index 22c8fa5a..15858362 100644 --- a/src/core/devices/nm-device-factory.c +++ b/src/core/devices/nm-device-factory.c @@ -147,7 +147,7 @@ nm_device_factory_get_connection_iface(NMDeviceFactory *factory, g_set_error(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "failed to determine interface name: error determine name for %s", + "failed to determine interface name for a %s", nm_connection_get_connection_type(connection)); return NULL; } @@ -415,6 +415,7 @@ nm_device_factory_manager_load_factories(NMDeviceFactoryManagerFactoryFunc callb _ADD_INTERNAL(nm_hsr_device_factory_get_type); _ADD_INTERNAL(nm_infiniband_device_factory_get_type); _ADD_INTERNAL(nm_ip_tunnel_device_factory_get_type); + _ADD_INTERNAL(nm_ipvlan_device_factory_get_type); _ADD_INTERNAL(nm_loopback_device_factory_get_type); _ADD_INTERNAL(nm_macsec_device_factory_get_type); _ADD_INTERNAL(nm_macvlan_device_factory_get_type); diff --git a/src/core/devices/nm-device-factory.h b/src/core/devices/nm-device-factory.h index 004ae9b1..d4aae75f 100644 --- a/src/core/devices/nm-device-factory.h +++ b/src/core/devices/nm-device-factory.h @@ -69,11 +69,15 @@ typedef struct { /** * get_connection_parent: * @factory: the #NMDeviceFactory - * @connection: the #NMConnection to return the parent name for, if supported + * @connection: the #NMConnection (possibly incomplete) to return the parent name for, if supported * * Given a connection, returns the parent interface name, parent connection * UUID, or parent device permanent hardware address for @connection. * + * Note that @connection is not necessarily a valid connection. + * It might be called during AddAndActivate before the connection is + * completed and normalized. + * * Returns: the parent interface name, parent connection UUID, parent * device permanent hardware address, or %NULL */ @@ -82,12 +86,16 @@ typedef struct { /** * get_connection_iface: * @factory: the #NMDeviceFactory - * @connection: the #NMConnection to return the interface name for + * @connection: the #NMConnection (possibly incomplete) to return the interface name for * @parent_iface: optional parent interface name for virtual devices * * Given a connection, returns the interface name that a device activating * that connection would have. * + * Note that @connection is not necessarily a valid connection. + * It might be called during AddAndActivate before the connection is + * completed and normalized. + * * Returns: the interface name, or %NULL */ char *(*get_connection_iface)(NMDeviceFactory *factory, diff --git a/src/core/devices/nm-device-infiniband.c b/src/core/devices/nm-device-infiniband.c index c974696c..a5a82b94 100644 --- a/src/core/devices/nm-device-infiniband.c +++ b/src/core/devices/nm-device-infiniband.c @@ -159,8 +159,7 @@ complete_connection(NMDevice *device, NULL, _("InfiniBand connection"), NULL, - nm_setting_infiniband_get_mac_address(s_infiniband) ? NULL : nm_device_get_iface(device), - TRUE); + nm_setting_infiniband_get_mac_address(s_infiniband) ? NULL : nm_device_get_iface(device)); if (!nm_setting_infiniband_get_transport_mode(s_infiniband)) g_object_set(G_OBJECT(s_infiniband), @@ -464,9 +463,10 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) NULL); s_infiniband = nm_connection_get_setting_infiniband(connection); - g_assert(s_infiniband); - - return nm_setting_infiniband_get_parent(s_infiniband); + if (s_infiniband) + return nm_setting_infiniband_get_parent(s_infiniband); + else + return NULL; } static char * @@ -477,17 +477,19 @@ get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const c g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_INFINIBAND_SETTING_NAME), NULL); - s_infiniband = nm_connection_get_setting_infiniband(connection); - g_assert(s_infiniband); - if (!parent_iface) return NULL; - g_return_val_if_fail(g_strcmp0(parent_iface, nm_setting_infiniband_get_parent(s_infiniband)) - == 0, - NULL); + s_infiniband = nm_connection_get_setting_infiniband(connection); + if (s_infiniband) { + g_return_val_if_fail(g_strcmp0(parent_iface, nm_setting_infiniband_get_parent(s_infiniband)) + == 0, + NULL); - return g_strdup(nm_setting_infiniband_get_virtual_interface_name(s_infiniband)); + return g_strdup(nm_setting_infiniband_get_virtual_interface_name(s_infiniband)); + } else { + return NULL; + } } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c index cc62180e..2ecfe453 100644 --- a/src/core/devices/nm-device-ip-tunnel.c +++ b/src/core/devices/nm-device-ip-tunnel.c @@ -402,8 +402,7 @@ complete_connection(NMDevice *device, NULL, _("IP tunnel connection"), NULL, - NULL, - TRUE); + NULL); s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection); if (!s_ip_tunnel) { @@ -1369,29 +1368,10 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) NULL); s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection); - g_assert(s_ip_tunnel); - - return nm_setting_ip_tunnel_get_parent(s_ip_tunnel); -} - -static char * -get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) -{ - const char *ifname; - NMSettingIPTunnel *s_ip_tunnel; - - g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_IP_TUNNEL_SETTING_NAME), - NULL); - - s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection); - g_assert(s_ip_tunnel); - - if (nm_setting_ip_tunnel_get_parent(s_ip_tunnel) && !parent_iface) + if (s_ip_tunnel) + return nm_setting_ip_tunnel_get_parent(s_ip_tunnel); + else return NULL; - - ifname = nm_connection_get_interface_name(connection); - - return g_strdup(ifname); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( @@ -1409,5 +1389,4 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL( NM_LINK_TYPE_VTI6) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_IP_TUNNEL_SETTING_NAME), factory_class->create_device = create_device; - factory_class->get_connection_parent = get_connection_parent; - factory_class->get_connection_iface = get_connection_iface;); + factory_class->get_connection_parent = get_connection_parent;); diff --git a/src/core/devices/nm-device-ipvlan.c b/src/core/devices/nm-device-ipvlan.c new file mode 100644 index 00000000..00a1b579 --- /dev/null +++ b/src/core/devices/nm-device-ipvlan.c @@ -0,0 +1,467 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Red Hat, Inc. + */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-device-ipvlan.h" + +#include + +#include "libnm-core-intern/nm-core-internal.h" +#include "nm-device-private.h" +#include "settings/nm-settings.h" +#include "nm-act-request.h" +#include "nm-manager.h" +#include "libnm-core-aux-intern/nm-libnm-core-utils.h" +#include "libnm-platform/nm-platform.h" +#include "nm-device-factory.h" +#include "nm-setting-ipvlan.h" +#include "nm-setting-wired.h" +#include "nm-active-connection.h" +#include "nm-utils.h" + +#define _NMLOG_DEVICE_TYPE NMDeviceIpvlan +#include "nm-device-logging.h" + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceIpvlan, PROP_MODE, PROP_PRIVATE, PROP_VEPA, ); + +typedef struct { + NMPlatformLnkIpvlan props; +} NMDeviceIpvlanPrivate; + +struct _NMDeviceIpvlan { + NMDevice parent; + NMDeviceIpvlanPrivate _priv; +}; + +struct _NMDeviceIpvlanClass { + NMDeviceClass parent; +}; + +G_DEFINE_TYPE(NMDeviceIpvlan, nm_device_ipvlan, NM_TYPE_DEVICE); + +#define NM_DEVICE_IPVLAN_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDeviceIpvlan, NM_IS_DEVICE_IPVLAN, NMDevice) + +/*****************************************************************************/ + +static int modes[][2] = { + {NM_SETTING_IPVLAN_MODE_L2, IPVLAN_MODE_L2}, + {NM_SETTING_IPVLAN_MODE_L3, IPVLAN_MODE_L3}, + {NM_SETTING_IPVLAN_MODE_L3S, IPVLAN_MODE_L3S}, +}; + +static int +setting_mode_to_platform(int mode) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS(modes); i++) { + if (modes[i][0] == mode) + return modes[i][1]; + } + + return -1; +} + +static int +platform_mode_to_setting(int mode) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS(modes); i++) { + if (modes[i][1] == mode) + return modes[i][0]; + } + + return 0; +} + +static const char * +platform_mode_to_string(guint mode) +{ + switch (mode) { + case IPVLAN_MODE_L2: + return "l2"; + case IPVLAN_MODE_L3: + return "l3"; + case IPVLAN_MODE_L3S: + return "l3s"; + default: + return "unknown"; + } +} + +/*****************************************************************************/ + +static void +update_properties(NMDevice *device) +{ + NMDeviceIpvlan *self = NM_DEVICE_IPVLAN(device); + NMDeviceIpvlanPrivate *priv = NM_DEVICE_IPVLAN_GET_PRIVATE(self); + GObject *object = G_OBJECT(device); + const NMPlatformLnkIpvlan *props; + const NMPlatformLink *plink; + + props = nm_platform_link_get_lnk_ipvlan(nm_device_get_platform(device), + nm_device_get_ifindex(device), + &plink); + + if (!props) { + _LOGW(LOGD_PLATFORM, "could not get IPVLAN properties"); + return; + } + + g_object_freeze_notify(object); + + nm_device_parent_set_ifindex(device, plink->parent); + +#define CHECK_PROPERTY_CHANGED(field, prop) \ + G_STMT_START \ + { \ + if (priv->props.field != props->field) { \ + priv->props.field = props->field; \ + _notify(self, prop); \ + } \ + } \ + G_STMT_END + + CHECK_PROPERTY_CHANGED(mode, PROP_MODE); + CHECK_PROPERTY_CHANGED(private_flag, PROP_PRIVATE); + CHECK_PROPERTY_CHANGED(vepa, PROP_VEPA); + + g_object_thaw_notify(object); +} + +static void +link_changed(NMDevice *device, const NMPlatformLink *pllink) +{ + NM_DEVICE_CLASS(nm_device_ipvlan_parent_class)->link_changed(device, pllink); + update_properties(device); +} + +static gboolean +create_and_realize(NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface(device); + NMSettingIpvlan *s_ipvlan; + NMPlatformLnkIpvlan lnk = {}; + int parent_ifindex; + int r; + + s_ipvlan = _nm_connection_get_setting(connection, NM_TYPE_SETTING_IPVLAN); + nm_assert(s_ipvlan); + + if (!parent) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_MISSING_DEPENDENCIES, + "IPVLAN device cannot be created without a parent interface"); + return FALSE; + } + + parent_ifindex = nm_device_get_ifindex(parent); + if (parent_ifindex <= 0) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_MISSING_DEPENDENCIES, + "cannot retrieve ifindex of interface %s (%s)", + nm_device_get_iface(parent), + nm_device_get_type_desc(parent)); + return FALSE; + } + + if (setting_mode_to_platform(nm_setting_ipvlan_get_mode(s_ipvlan)) < 0) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "unsupported IPVLAN mode %u", + nm_setting_ipvlan_get_mode(s_ipvlan)); + return FALSE; + } + lnk.mode = setting_mode_to_platform(nm_setting_ipvlan_get_mode(s_ipvlan)); + lnk.private_flag = nm_setting_ipvlan_get_private(s_ipvlan); + lnk.vepa = nm_setting_ipvlan_get_vepa(s_ipvlan); + + r = nm_platform_link_ipvlan_add(nm_device_get_platform(device), + iface, + parent_ifindex, + &lnk, + out_plink); + + if (r < 0) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create IPVLAN interface '%s' for '%s': %s", + iface, + nm_connection_get_id(connection), + nm_strerror(r)); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static NMDeviceCapabilities +get_generic_capabilities(NMDevice *device) +{ + return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE; +} + +/*****************************************************************************/ + +static gboolean +is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +{ + if (!nm_device_parent_get_device(device)) + return FALSE; + return NM_DEVICE_CLASS(nm_device_ipvlan_parent_class)->is_available(device, flags); +} + +/*****************************************************************************/ + +static gboolean +check_connection_compatible(NMDevice *device, + NMConnection *connection, + gboolean check_properties, + GError **error) +{ + NMDeviceIpvlanPrivate *priv = NM_DEVICE_IPVLAN_GET_PRIVATE(device); + NMSettingIpvlan *s_ipvlan; + const char *parent = NULL; + + if (!NM_DEVICE_CLASS(nm_device_ipvlan_parent_class) + ->check_connection_compatible(device, connection, check_properties, error)) + return FALSE; + + s_ipvlan = _nm_connection_get_setting(connection, NM_TYPE_SETTING_IPVLAN); + + if (check_properties && nm_device_is_real(device)) { + if (setting_mode_to_platform(nm_setting_ipvlan_get_mode(s_ipvlan)) != priv->props.mode) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "IPVLAN mode setting differs"); + return FALSE; + } + + if (nm_setting_ipvlan_get_private(s_ipvlan) != priv->props.private_flag) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "IPVLAN private flag setting differs"); + return FALSE; + } + if (nm_setting_ipvlan_get_vepa(s_ipvlan) != priv->props.vepa) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "IPVLAN VEPA flag setting differs"); + return FALSE; + } + + /* Check parent interface; could be an interface name or a UUID */ + parent = nm_setting_ipvlan_get_parent(s_ipvlan); + if (parent) { + if (!nm_device_match_parent(device, parent)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "IPVLAN parent setting differs"); + return FALSE; + } + } else { + /* Parent could be a MAC address in an NMSettingWired */ + if (!nm_device_match_parent_hwaddr(device, connection, TRUE)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + "IPVLAN parent mac setting differs"); + return FALSE; + } + } + } + return TRUE; +} + +static void +update_connection(NMDevice *device, NMConnection *connection) +{ + NMDeviceIpvlanPrivate *priv = NM_DEVICE_IPVLAN_GET_PRIVATE(device); + NMSettingIpvlan *s_ipvlan = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_IPVLAN); + + if (priv->props.mode != setting_mode_to_platform(nm_setting_ipvlan_get_mode(s_ipvlan))) + g_object_set(s_ipvlan, + NM_SETTING_IPVLAN_MODE, + platform_mode_to_setting(priv->props.mode), + NULL); + + if (priv->props.private_flag != nm_setting_ipvlan_get_private(s_ipvlan)) + g_object_set(s_ipvlan, NM_SETTING_IPVLAN_PRIVATE, priv->props.private_flag, NULL); + + if (priv->props.vepa != nm_setting_ipvlan_get_vepa(s_ipvlan)) + g_object_set(s_ipvlan, NM_SETTING_IPVLAN_VEPA, priv->props.vepa, NULL); + + g_object_set( + s_ipvlan, + NM_SETTING_IPVLAN_PARENT, + nm_device_parent_find_for_connection(device, nm_setting_ipvlan_get_parent(s_ipvlan)), + NULL); +} + +/*****************************************************************************/ + +static void +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + NMDeviceIpvlanPrivate *priv = NM_DEVICE_IPVLAN_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_MODE: + g_value_set_string(value, platform_mode_to_string(priv->props.mode)); + break; + case PROP_PRIVATE: + g_value_set_boolean(value, priv->props.private_flag); + break; + case PROP_VEPA: + g_value_set_boolean(value, priv->props.vepa); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_device_ipvlan_init(NMDeviceIpvlan *self) +{} + +static const NMDBusInterfaceInfoExtended interface_info_device_ipvlan = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( + NM_DBUS_INTERFACE_DEVICE_IPVLAN, + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Parent", "o", NM_DEVICE_PARENT), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Mode", "s", NM_DEVICE_IPVLAN_MODE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Private", + "b", + NM_DEVICE_IPVLAN_PRIVATE), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Vepa", + "b", + NM_DEVICE_IPVLAN_VEPA), ), ), +}; + +static void +nm_device_ipvlan_class_init(NMDeviceIpvlanClass *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; + + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ipvlan); + + device_class->connection_type_supported = NM_SETTING_IPVLAN_SETTING_NAME; + device_class->connection_type_check_compatible = NM_SETTING_IPVLAN_SETTING_NAME; + device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_IPVLAN); + + device_class->check_connection_compatible = check_connection_compatible; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->is_available = is_available; + device_class->link_changed = link_changed; + device_class->update_connection = update_connection; + + obj_properties[PROP_MODE] = g_param_spec_string(NM_DEVICE_IPVLAN_MODE, + "", + "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_PRIVATE] = g_param_spec_boolean(NM_DEVICE_IPVLAN_PRIVATE, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_VEPA] = g_param_spec_boolean(NM_DEVICE_IPVLAN_VEPA, + "", + "", + TRUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} + +/*****************************************************************************/ + +#define NM_TYPE_IPVLAN_DEVICE_FACTORY (nm_ipvlan_device_factory_get_type()) +#define NM_IPVLAN_DEVICE_FACTORY(obj) \ + (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IPVLAN_DEVICE_FACTORY, NMIpvlanDeviceFactory)) + +static NMDevice * +create_device(NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) +{ + NMSettingIpvlan *s_ipvlan; + + if (connection) { + s_ipvlan = _nm_connection_get_setting(connection, NM_TYPE_SETTING_IPVLAN); + nm_assert(s_ipvlan); + } + + return g_object_new(NM_TYPE_DEVICE_IPVLAN, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Ipvlan", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_IPVLAN, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_IPVLAN, + NULL); +} + +static const char * +get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingIpvlan *s_ipvlan; + NMSettingWired *s_wired; + const char *parent = NULL; + + g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_IPVLAN_SETTING_NAME), NULL); + + s_ipvlan = _nm_connection_get_setting(connection, NM_TYPE_SETTING_IPVLAN); + if (s_ipvlan) { + parent = nm_setting_ipvlan_get_parent(s_ipvlan); + if (parent) + return parent; + } + + /* Try the hardware address from the IPVLAN connection's hardware setting */ + s_wired = nm_connection_get_setting_wired(connection); + if (s_wired) + return nm_setting_wired_get_mac_address(s_wired); + else + return NULL; +} + +NM_DEVICE_FACTORY_DEFINE_INTERNAL( + IPVLAN, + Ipvlan, + ipvlan, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_IPVLAN) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_IPVLAN_SETTING_NAME), + factory_class->create_device = create_device; + factory_class->get_connection_parent = get_connection_parent;); diff --git a/src/core/devices/nm-device-ipvlan.h b/src/core/devices/nm-device-ipvlan.h new file mode 100644 index 00000000..6a228abe --- /dev/null +++ b/src/core/devices/nm-device-ipvlan.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_DEVICE_IPVLAN_H__ +#define __NETWORKMANAGER_DEVICE_IPVLAN_H__ + +#include "nm-device.h" + +#define NM_TYPE_DEVICE_IPVLAN (nm_device_ipvlan_get_type()) +#define NM_DEVICE_IPVLAN(obj) \ + (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_IPVLAN, NMDeviceIpvlan)) +#define NM_DEVICE_IPVLAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_IPVLAN, NMDeviceIpvlanClass)) +#define NM_IS_DEVICE_IPVLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_IPVLAN)) +#define NM_IS_DEVICE_IPVLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_IPVLAN)) +#define NM_DEVICE_IPVLAN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_IPVLAN, NMDeviceIpvlanClass)) + +#define NM_DEVICE_IPVLAN_PARENT "parent" +#define NM_DEVICE_IPVLAN_MODE "mode" +#define NM_DEVICE_IPVLAN_PRIVATE "private" +#define NM_DEVICE_IPVLAN_VEPA "vepa" + +typedef struct _NMDeviceIpvlan NMDeviceIpvlan; +typedef struct _NMDeviceIpvlanClass NMDeviceIpvlanClass; + +GType nm_device_ipvlan_get_type(void); + +#endif /* __NETWORKMANAGER_DEVICE_IPVLAN_H__ */ diff --git a/src/core/devices/nm-device-loopback.c b/src/core/devices/nm-device-loopback.c index ec72aa96..268e1fb1 100644 --- a/src/core/devices/nm-device-loopback.c +++ b/src/core/devices/nm-device-loopback.c @@ -59,14 +59,14 @@ complete_connection(NMDevice *device, NMConnection *const *existing_connections, GError **error) { - nm_utils_complete_generic_with_params(nm_device_get_platform(device), - connection, - NM_SETTING_LOOPBACK_SETTING_NAME, - existing_connections, - NULL, - _("Loopback connection"), - NULL, - nm_device_get_ip_iface(device)); + nm_utils_complete_generic(nm_device_get_platform(device), + connection, + NM_SETTING_LOOPBACK_SETTING_NAME, + existing_connections, + NULL, + _("Loopback connection"), + NULL, + nm_device_get_ip_iface(device)); _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_LOOPBACK); diff --git a/src/core/devices/nm-device-macsec.c b/src/core/devices/nm-device-macsec.c index 32fab5be..89a06720 100644 --- a/src/core/devices/nm-device-macsec.c +++ b/src/core/devices/nm-device-macsec.c @@ -1022,36 +1022,18 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACSEC_SETTING_NAME), NULL); s_macsec = nm_connection_get_setting_macsec(connection); - g_assert(s_macsec); - - parent = nm_setting_macsec_get_parent(s_macsec); - if (parent) - return parent; + if (s_macsec) { + parent = nm_setting_macsec_get_parent(s_macsec); + if (parent) + return parent; + } /* Try the hardware address from the MACsec connection's hardware setting */ s_wired = nm_connection_get_setting_wired(connection); if (s_wired) return nm_setting_wired_get_mac_address(s_wired); - - return NULL; -} - -static char * -get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) -{ - NMSettingMacsec *s_macsec; - const char *ifname; - - g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACSEC_SETTING_NAME), NULL); - - s_macsec = nm_connection_get_setting_macsec(connection); - g_assert(s_macsec); - - if (!parent_iface) + else return NULL; - - ifname = nm_connection_get_interface_name(connection); - return g_strdup(ifname); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( @@ -1061,5 +1043,4 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL( NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_MACSEC) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_MACSEC_SETTING_NAME), factory_class->create_device = create_device; - factory_class->get_connection_parent = get_connection_parent; - factory_class->get_connection_iface = get_connection_iface;) + factory_class->get_connection_parent = get_connection_parent;); diff --git a/src/core/devices/nm-device-macvlan.c b/src/core/devices/nm-device-macvlan.c index 8cdef0cf..9501e8f1 100644 --- a/src/core/devices/nm-device-macvlan.c +++ b/src/core/devices/nm-device-macvlan.c @@ -232,9 +232,8 @@ create_and_realize(NMDevice *device, g_set_error(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, - "unsupported MACVLAN mode %u in connection %s", - nm_setting_macvlan_get_mode(s_macvlan), - nm_connection_get_uuid(connection)); + "unsupported MACVLAN mode %u", + nm_setting_macvlan_get_mode(s_macvlan)); return FALSE; } lnk.no_promisc = !nm_setting_macvlan_get_promiscuous(s_macvlan); @@ -365,8 +364,7 @@ complete_connection(NMDevice *device, NULL, _("MACVLAN connection"), NULL, - NULL, - TRUE); + NULL); s_macvlan = nm_connection_get_setting_macvlan(connection); if (!s_macvlan) { @@ -590,36 +588,18 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACVLAN_SETTING_NAME), NULL); s_macvlan = nm_connection_get_setting_macvlan(connection); - g_assert(s_macvlan); - - parent = nm_setting_macvlan_get_parent(s_macvlan); - if (parent) - return parent; + if (s_macvlan) { + parent = nm_setting_macvlan_get_parent(s_macvlan); + if (parent) + return parent; + } /* Try the hardware address from the MACVLAN connection's hardware setting */ s_wired = nm_connection_get_setting_wired(connection); if (s_wired) return nm_setting_wired_get_mac_address(s_wired); - - return NULL; -} - -static char * -get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) -{ - NMSettingMacvlan *s_macvlan; - const char *ifname; - - g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_MACVLAN_SETTING_NAME), NULL); - - s_macvlan = nm_connection_get_setting_macvlan(connection); - g_assert(s_macvlan); - - if (!parent_iface) + else return NULL; - - ifname = nm_connection_get_interface_name(connection); - return g_strdup(ifname); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( @@ -629,5 +609,4 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL( NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_MACVLAN_SETTING_NAME), factory_class->create_device = create_device; - factory_class->get_connection_parent = get_connection_parent; - factory_class->get_connection_iface = get_connection_iface;); + factory_class->get_connection_parent = get_connection_parent;); diff --git a/src/core/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c index 27566607..f44fe2f0 100644 --- a/src/core/devices/nm-device-ppp.c +++ b/src/core/devices/nm-device-ppp.c @@ -188,7 +188,7 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) 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){ + 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, @@ -380,20 +380,10 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) nm_assert(nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)); s_pppoe = nm_connection_get_setting_pppoe(connection); - nm_assert(s_pppoe); - - return nm_setting_pppoe_get_parent(s_pppoe); -} - -static char * -get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) -{ - nm_assert(nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)); - - if (!parent_iface) + if (s_pppoe) + return nm_setting_pppoe_get_parent(s_pppoe); + else return NULL; - - return g_strdup(nm_connection_get_interface_name(connection)); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( @@ -403,6 +393,5 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL( NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_PPP) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_PPPOE_SETTING_NAME), factory_class->get_connection_parent = get_connection_parent; - factory_class->get_connection_iface = get_connection_iface; factory_class->create_device = create_device; factory_class->match_connection = match_connection;); diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h index 3bf5925c..2f73a01b 100644 --- a/src/core/devices/nm-device-private.h +++ b/src/core/devices/nm-device-private.h @@ -115,8 +115,8 @@ gboolean nm_device_sysctl_ip_conf_set(NMDevice *self, NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source); -const NML3ConfigData *nm_device_create_l3_config_data_from_connection(NMDevice *self, - NMConnection *connection); +NML3ConfigData *nm_device_create_l3_config_data_from_connection(NMDevice *self, + NMConnection *connection); void nm_device_ip_method_dhcp4_start(NMDevice *self); diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index 28b03cec..faab86d0 100644 --- a/src/core/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -143,8 +143,7 @@ complete_connection(NMDevice *device, NULL, _("TUN connection"), NULL, - NULL, - TRUE); + NULL); s_tun = nm_connection_get_setting_tun(connection); if (!s_tun) { diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c index ccb6292b..9fd7ac9d 100644 --- a/src/core/devices/nm-device-utils.c +++ b/src/core/devices/nm-device-utils.c @@ -355,7 +355,7 @@ nm_device_resolve_address(int addr_family, NMDnsSystemdResolved *resolved; info = g_new(ResolveAddrInfo, 1); - *info = (ResolveAddrInfo){ + *info = (ResolveAddrInfo) { .task = nm_g_task_new(NULL, cancellable, nm_device_resolve_address, callback, cb_data), .addr_family = addr_family, .address = nm_ip_addr_init(addr_family, address), diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c index d4630999..59a429ca 100644 --- a/src/core/devices/nm-device-vlan.c +++ b/src/core/devices/nm-device-vlan.c @@ -241,7 +241,7 @@ create_and_realize(NMDevice *device, r = nm_platform_link_vlan_add(nm_device_get_platform(device), iface, parent_ifindex, - &((NMPlatformLnkVlan){ + &((NMPlatformLnkVlan) { .id = vlan_id, .flags = nm_setting_vlan_get_flags(s_vlan), .protocol = protocol, @@ -379,8 +379,7 @@ complete_connection(NMDevice *device, NULL, _("VLAN connection"), NULL, - NULL, - TRUE); + NULL); s_vlan = nm_connection_get_setting_vlan(connection); if (!s_vlan) { @@ -618,43 +617,35 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_VLAN_SETTING_NAME), NULL); s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); - - parent = nm_setting_vlan_get_parent(s_vlan); - if (parent) - return parent; + if (s_vlan) { + parent = nm_setting_vlan_get_parent(s_vlan); + if (parent) + return parent; + } /* Try the hardware address from the VLAN connection's hardware setting */ s_wired = nm_connection_get_setting_wired(connection); if (s_wired) return nm_setting_wired_get_mac_address(s_wired); - - return NULL; + else + return NULL; } static char * get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) { - const char *ifname; NMSettingVlan *s_vlan; g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_VLAN_SETTING_NAME), NULL); - s_vlan = nm_connection_get_setting_vlan(connection); - g_assert(s_vlan); - if (!parent_iface) return NULL; - ifname = nm_connection_get_interface_name(connection); - if (ifname) - return g_strdup(ifname); - - /* If the connection doesn't specify the interface name for the VLAN - * device, we create one for it using the VLAN ID and the parent - * interface's name. - */ - return nmp_utils_new_vlan_name(parent_iface, nm_setting_vlan_get_id(s_vlan)); + s_vlan = nm_connection_get_setting_vlan(connection); + if (s_vlan) + return nmp_utils_new_vlan_name(parent_iface, nm_setting_vlan_get_id(s_vlan)); + else + return NULL; } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/core/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index c3d31347..7dfd6504 100644 --- a/src/core/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -48,7 +48,7 @@ do_update_properties(NMDeviceVrf *self, const NMPlatformLnkVrf *props) NMPlatformLnkVrf props_null; if (!props) { - props_null = (NMPlatformLnkVrf){}; + props_null = (NMPlatformLnkVrf) {}; props = &props_null; } @@ -184,8 +184,7 @@ complete_connection(NMDevice *device, NULL, _("VRF connection"), NULL, - NULL, - TRUE); + NULL); s_vrf = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VRF); if (!s_vrf) { diff --git a/src/core/devices/nm-device-vxlan.c b/src/core/devices/nm-device-vxlan.c index 6a23d51e..4058287c 100644 --- a/src/core/devices/nm-device-vxlan.c +++ b/src/core/devices/nm-device-vxlan.c @@ -384,8 +384,7 @@ complete_connection(NMDevice *device, NULL, _("VXLAN connection"), NULL, - NULL, - TRUE); + NULL); s_vxlan = nm_connection_get_setting_vxlan(connection); if (!s_vxlan) { @@ -777,27 +776,10 @@ get_connection_parent(NMDeviceFactory *factory, NMConnection *connection) g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_VXLAN_SETTING_NAME), NULL); s_vxlan = nm_connection_get_setting_vxlan(connection); - g_assert(s_vxlan); - - return nm_setting_vxlan_get_parent(s_vxlan); -} - -static char * -get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface) -{ - const char *ifname; - NMSettingVxlan *s_vxlan; - - g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_VXLAN_SETTING_NAME), NULL); - - s_vxlan = nm_connection_get_setting_vxlan(connection); - g_assert(s_vxlan); - - if (nm_setting_vxlan_get_parent(s_vxlan) && !parent_iface) + if (s_vxlan) + return nm_setting_vxlan_get_parent(s_vxlan); + else return NULL; - - ifname = nm_connection_get_interface_name(connection); - return g_strdup(ifname); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( @@ -807,5 +789,4 @@ NM_DEVICE_FACTORY_DEFINE_INTERNAL( NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_VXLAN) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_VXLAN_SETTING_NAME), factory_class->create_device = create_device; - factory_class->get_connection_parent = get_connection_parent; - factory_class->get_connection_iface = get_connection_iface;); + factory_class->get_connection_parent = get_connection_parent;); diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index 00a8c718..4a08192e 100644 --- a/src/core/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -430,7 +430,7 @@ get_extra_rules(NMDevice *device) g_ptr_array_add(extra_rules, nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, - &((const NMPlatformRoutingRule){ + &((const NMPlatformRoutingRule) { .priority = priority, .addr_family = addr_family, .action = FR_ACT_TO_TBL, @@ -440,7 +440,7 @@ get_extra_rules(NMDevice *device) g_ptr_array_add(extra_rules, nmp_object_new(NMP_OBJECT_TYPE_ROUTING_RULE, - &((const NMPlatformRoutingRule){ + &((const NMPlatformRoutingRule) { .priority = priority + 1u, .addr_family = addr_family, .action = FR_ACT_TO_TBL, @@ -588,7 +588,7 @@ _peers_add(NMDeviceWireGuard *self, NMWireGuardPeer *peer) nm_assert(!_peers_find(priv, peer)); peer_data = g_slice_new(PeerData); - *peer_data = (PeerData){ + *peer_data = (PeerData) { .self = self, .peer = nm_wireguard_peer_ref(peer), .ep_resolv = @@ -792,7 +792,7 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) switch (g_inet_address_get_family(a)) { case G_SOCKET_FAMILY_IPV4: nm_assert(g_inet_address_get_native_size(a) == sizeof(struct in_addr)); - s->in = (struct sockaddr_in){ + s->in = (struct sockaddr_in) { .sin_family = AF_INET, .sin_port = htons(nm_sock_addr_endpoint_get_port( _nm_wireguard_peer_get_endpoint(peer_data->peer))), @@ -801,7 +801,7 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) break; case G_SOCKET_FAMILY_IPV6: nm_assert(g_inet_address_get_native_size(a) == sizeof(struct in6_addr)); - s->in6 = (struct sockaddr_in6){ + s->in6 = (struct sockaddr_in6) { .sin6_family = AF_INET6, .sin6_port = htons(nm_sock_addr_endpoint_get_port( _nm_wireguard_peer_get_endpoint(peer_data->peer))), @@ -985,7 +985,7 @@ _peers_update(NMDeviceWireGuard *self, if (nm_clear_g_cancellable(&peer_data->ep_resolv.cancellable)) _peers_resolving_cnt_decrement(self); - peer_data->ep_resolv = (PeerEndpointResolveData){ + peer_data->ep_resolv = (PeerEndpointResolveData) { .sockaddr = sockaddr, .resolv_fail_count = 0, .cancellable = NULL, @@ -1166,7 +1166,7 @@ _peers_get_platform_list(NMDeviceWireGuardPrivate *priv, prefix = addr_family == AF_INET ? 32 : 128; g_array_append_val(allowed_ips, - ((NMPWireGuardAllowedIP){ + ((NMPWireGuardAllowedIP) { .family = addr_family, .mask = prefix, .addr = addrbin, @@ -1486,7 +1486,7 @@ link_config(NMDeviceWireGuard *self, _peers_update_all(self, s_wg, &peers_removed); - wg_lnk = (NMPlatformLnkWireGuard){}; + wg_lnk = (NMPlatformLnkWireGuard) {}; wg_change_flags = NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE; @@ -1733,7 +1733,7 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family) } if (addr_family == AF_INET) { - rt.r4 = (NMPlatformIP4Route){ + rt.r4 = (NMPlatformIP4Route) { .network = addrbin.addr4, .plen = prefix, .ifindex = ip_ifindex, @@ -1742,7 +1742,7 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family) .metric = route_metric, }; } else { - rt.r6 = (NMPlatformIP6Route){ + rt.r6 = (NMPlatformIP6Route) { .network = addrbin.addr6, .plen = prefix, .ifindex = ip_ifindex, diff --git a/src/core/devices/nm-device-wpan.c b/src/core/devices/nm-device-wpan.c index 7885355d..67f845c8 100644 --- a/src/core/devices/nm-device-wpan.c +++ b/src/core/devices/nm-device-wpan.c @@ -53,8 +53,7 @@ complete_connection(NMDevice *device, NULL, _("WPAN connection"), NULL, - NULL, - TRUE); + NULL); s_wpan = NM_SETTING_WPAN(nm_connection_get_setting(connection, NM_TYPE_SETTING_WPAN)); if (!s_wpan) { diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 6c5a9b5a..e310a9c6 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -283,6 +283,7 @@ typedef struct { NML3IPv4LL *ipv4ll; NML3IPv4LLRegistration *ipv4ll_registation; GSource *timeout_source; + NMSettingIP4LinkLocal mode; } v4; struct { NML3IPv6LL *ipv6ll; @@ -315,6 +316,7 @@ typedef struct { NMEthtoolPauseState *pause; NMEthtoolChannelsState *channels; NMEthtoolEEEState *eee; + uint32_t fec_mode; } EthtoolState; typedef enum { @@ -615,6 +617,9 @@ typedef struct _NMDevicePrivate { NMPacrunnerConfId *pacrunner_conf_id; + const char *ipv4_method; + const char *ipv6_method; + struct { union { const NMDeviceIPState state; @@ -694,16 +699,6 @@ typedef struct _NMDevicePrivate { bool previous_mode_has : 1; } addrgenmode6_data; - struct { - NMLogDomain log_domain; - guint timeout; - guint watch; - GPid pid; - char *binary; - char *address; - guint deadline; - } gw_ping; - /* Firewall */ FirewallState fw_state : 4; NMFirewalldManager *fw_mgr; @@ -781,6 +776,8 @@ typedef struct _NMDevicePrivate { GVariant *ports_variant; /* Array of port devices D-Bus path */ char *prop_ip_iface; /* IP interface D-Bus property */ + GList *ping_operations; + GSource *ping_timeout; } NMDevicePrivate; G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT) @@ -837,6 +834,7 @@ static void _set_mtu(NMDevice *self, guint32 mtu); static void _commit_mtu(NMDevice *self); static void _cancel_activation(NMDevice *self); +static void _dev_ipll4_check_fallback(NMDevice *self, const NML3ConfigData *l3cd_new); static void _dev_ipll4_notify_event(NMDevice *self); static void _dev_ip_state_check(NMDevice *self, int addr_family); @@ -1357,6 +1355,42 @@ _prop_get_ipv6_ra_timeout(NMDevice *self) 0); } +static NMSettingIPConfigRoutedDns +_prop_get_ipvx_routed_dns(NMDevice *self, int addr_family) +{ + NMSettingIPConfig *s_ip; + NMSettingIPConfigRoutedDns val; + int IS_IPv4; + const char *dns_mode; + NMSettingIPConfigRoutedDns fallback_value = NM_SETTING_IP_CONFIG_ROUTED_DNS_NO; + + g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_IP_CONFIG_ROUTED_DNS_NO); + IS_IPv4 = NM_IS_IPv4(addr_family); + + s_ip = nm_device_get_applied_setting(self, + IS_IPv4 ? NM_TYPE_SETTING_IP4_CONFIG + : NM_TYPE_SETTING_IP6_CONFIG); + if (!s_ip) + return NM_SETTING_IP_CONFIG_ROUTED_DNS_NO; + + val = nm_setting_ip_config_get_routed_dns(s_ip); + if (val != NM_SETTING_IP_CONFIG_ROUTED_DNS_DEFAULT) + return val; + + dns_mode = nm_config_data_get_dns_mode(nm_config_get_data(nm_config_get())); + if (nm_streq0(dns_mode, "dnsconfd")) { + fallback_value = NM_SETTING_IP_CONFIG_ROUTED_DNS_YES; + } + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + IS_IPv4 ? NM_CON_DEFAULT("ipv4.routed-dns") + : NM_CON_DEFAULT("ipv6.routed-dns"), + self, + NM_SETTING_IP_CONFIG_ROUTED_DNS_NO, + NM_SETTING_IP_CONFIG_ROUTED_DNS_YES, + fallback_value); +} + static NMSettingConnectionMdns _prop_get_connection_mdns(NMDevice *self) { @@ -1603,6 +1637,7 @@ _prop_get_ipv4_link_local(NMDevice *self) { NMSettingIP4Config *s_ip4; NMSettingIP4LinkLocal link_local; + const char *method; s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG); if (!s_ip4) @@ -1611,6 +1646,8 @@ _prop_get_ipv4_link_local(NMDevice *self) if (NM_IS_DEVICE_LOOPBACK(self)) return NM_SETTING_IP4_LL_DISABLED; + method = nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4); + link_local = nm_setting_ip4_config_get_link_local(s_ip4); if (link_local == NM_SETTING_IP4_LL_DEFAULT) { @@ -1620,31 +1657,45 @@ _prop_get_ipv4_link_local(NMDevice *self) NM_CON_DEFAULT("ipv4.link-local"), self, NM_SETTING_IP4_LL_AUTO, - NM_SETTING_IP4_LL_ENABLED, + NM_SETTING_IP4_LL_FALLBACK, NM_SETTING_IP4_LL_DEFAULT); if (link_local == NM_SETTING_IP4_LL_DEFAULT) { /* If there is no global configuration for ipv4.link-local assume auto */ link_local = NM_SETTING_IP4_LL_AUTO; - } else if (link_local == NM_SETTING_IP4_LL_ENABLED - && nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4), - NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { - /* ipv4.method=disabled has higher priority than the global ipv4.link-local=enabled */ + } else if (NM_IN_SET(link_local, NM_SETTING_IP4_LL_ENABLED, NM_SETTING_IP4_LL_FALLBACK) + && nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { + /* ipv4.method=disabled has higher priority than the global + * ipv4.link-local=enabled / ipv4.link-local=fallback */ link_local = NM_SETTING_IP4_LL_DISABLED; } else if (link_local == NM_SETTING_IP4_LL_DISABLED - && nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4), - NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { + && nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { /* ipv4.method=link-local has higher priority than the global ipv4.link-local=disabled */ link_local = NM_SETTING_IP4_LL_ENABLED; } } if (link_local == NM_SETTING_IP4_LL_AUTO) { - link_local = nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4), - NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) - ? NM_SETTING_IP4_LL_ENABLED - : NM_SETTING_IP4_LL_DISABLED; + /* ipv4.link-local=auto means enabled for ipv4.method=link-local, + * and disabled for anything else */ + if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { + link_local = NM_SETTING_IP4_LL_ENABLED; + } else { + link_local = NM_SETTING_IP4_LL_DISABLED; + } + } + + if (link_local == NM_SETTING_IP4_LL_FALLBACK + && nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { + /* ipv4.link-local=fallback with ipv4.method=link-local will + * always be on anyway, simplify logic */ + link_local = NM_SETTING_IP4_LL_ENABLED; } + nm_assert(NM_IN_SET(link_local, + NM_SETTING_IP4_LL_DISABLED, + NM_SETTING_IP4_LL_ENABLED, + NM_SETTING_IP4_LL_FALLBACK)); + return link_local; } @@ -1806,6 +1857,29 @@ _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)); } +static gboolean +_prop_get_ipv4_dhcp_ipv6_only_preferred(NMDevice *self) +{ + NMSettingIP4Config *s_ip4; + NMSettingIP4DhcpIpv6OnlyPreferred ipv6_only; + + s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG); + if (!s_ip4) + return FALSE; + + ipv6_only = nm_setting_ip4_config_get_dhcp_ipv6_only_preferred(s_ip4); + if (ipv6_only != NM_SETTING_IP4_DHCP_IPV6_ONLY_PREFERRED_DEFAULT) + return ipv6_only; + + return nm_config_data_get_connection_default_int64( + NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("ipv4.dhcp-ipv6-only-preferred"), + self, + NM_SETTING_IP4_DHCP_IPV6_ONLY_PREFERRED_NO, + NM_SETTING_IP4_DHCP_IPV6_ONLY_PREFERRED_YES, + NM_SETTING_IP4_DHCP_IPV6_ONLY_PREFERRED_NO); +} + /** * _prop_get_ipvx_dhcp_iaid: * @self: the #NMDevice @@ -2005,6 +2079,59 @@ _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family) return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6; } +static gboolean +_prop_get_ipvx_dhcp_send_hostname(NMDevice *self, int addr_family) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMSettingIPConfig *s_ip = IS_IPv4 + ? nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG) + : nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP6_CONFIG); + gboolean send_hostname; + gboolean send_hostname_v2; + + g_return_val_if_fail(s_ip, FALSE); + + send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip); + send_hostname_v2 = nm_setting_ip_config_get_dhcp_send_hostname_v2(s_ip); + + if (send_hostname_v2 == NM_TERNARY_DEFAULT) { + send_hostname_v2 = nm_config_data_get_connection_default_int64( + NM_CONFIG_GET_DATA, + IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-send-hostname") + : NM_CON_DEFAULT("ipv6.dhcp-send-hostname"), + self, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE, + send_hostname ? NM_TERNARY_TRUE : NM_TERNARY_FALSE); + } + + return send_hostname_v2; +} + +static gboolean +_prop_get_connection_ip_ping_addresses_require_all(NMDevice *self, NMSettingConnection *s_con) +{ + NMTernary ip_ping_addresses_require_all; + const char *s; + + ip_ping_addresses_require_all = nm_setting_connection_get_ip_ping_addresses_require_all(s_con); + + if (ip_ping_addresses_require_all != NM_TERNARY_DEFAULT) { + return ip_ping_addresses_require_all; + } else { + s = nm_config_data_get_connection_default( + NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("connection.ip-ping-addresses-require-all"), + self); + + if (s) { + return _nm_utils_ascii_str_to_bool(s, FALSE); + } + } + + return FALSE; +} + static const char * _prop_get_connection_mud_url(NMDevice *self, NMSettingConnection *s_con) { @@ -2563,6 +2690,19 @@ _ethtool_features_reset(NMDevice *self, NMPlatform *platform, EthtoolState *etht _LOGD(LOGD_DEVICE, "ethtool: offload features successfully reset"); } +static void +_ethtool_fec_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state) +{ + if (ethtool_state->fec_mode) { + if (!nm_platform_ethtool_set_fec_mode(platform, + ethtool_state->ifindex, + ethtool_state->fec_mode)) + _LOGW(LOGD_DEVICE, "ethtool: failure resetting FEC"); + else + _LOGD(LOGD_DEVICE, "ethtool: FEC successfully reset"); + } +} + static void _ethtool_features_set(NMDevice *self, NMPlatform *platform, @@ -2594,6 +2734,55 @@ _ethtool_features_set(NMDevice *self, ethtool_state->features = g_steal_pointer(&features); } +static void +_ethtool_fec_set(NMDevice *self, + NMPlatform *platform, + EthtoolState *ethtool_state, + NMSettingEthtool *s_ethtool) +{ + uint32_t old_fec_mode; + uint32_t fec_mode = NM_SETTING_ETHTOOL_FEC_MODE_NONE; + GHashTable *hash; + GHashTableIter iter; + const char *name; + GVariant *variant; + + nm_assert(NM_IS_DEVICE(self)); + nm_assert(NM_IS_PLATFORM(platform)); + nm_assert(NM_IS_SETTING_ETHTOOL(s_ethtool)); + nm_assert(ethtool_state); + nm_assert(!ethtool_state->fec_mode); + + hash = _nm_setting_option_hash(NM_SETTING(s_ethtool), FALSE); + if (!hash) + return; + + g_hash_table_iter_init(&iter, hash); + while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) { + NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name(name); + + if (!nm_ethtool_id_is_fec(ethtool_id)) + continue; + + nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32)); + fec_mode = g_variant_get_uint32(variant); + } + + nm_platform_ethtool_get_fec_mode(platform, ethtool_state->ifindex, &old_fec_mode); + + /* The NM_SETTING_ETHTOOL_FEC_MODE_NONE is query only value, hence do nothing. */ + if (!fec_mode || fec_mode == NM_SETTING_ETHTOOL_FEC_MODE_NONE) { + return; + } + + if (!nm_platform_ethtool_set_fec_mode(platform, ethtool_state->ifindex, fec_mode)) + _LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d", fec_mode); + else { + _LOGD(LOGD_DEVICE, "ethtool: FEC %d successfully set", fec_mode); + ethtool_state->fec_mode = old_fec_mode; + } +} + static void _ethtool_coalesce_reset(NMDevice *self, NMPlatform *platform, EthtoolState *ethtool_state) { @@ -3075,6 +3264,7 @@ _ethtool_state_reset(NMDevice *self) _ethtool_pause_reset(self, platform, ethtool_state); _ethtool_channels_reset(self, platform, ethtool_state); _ethtool_eee_reset(self, platform, ethtool_state); + _ethtool_fec_reset(self, platform, ethtool_state); } static void @@ -3111,9 +3301,11 @@ _ethtool_state_set(NMDevice *self) _ethtool_pause_set(self, platform, ethtool_state, s_ethtool); _ethtool_channels_set(self, platform, ethtool_state, s_ethtool); _ethtool_eee_set(self, platform, ethtool_state, s_ethtool); + _ethtool_fec_set(self, platform, ethtool_state, s_ethtool); if (ethtool_state->features || ethtool_state->coalesce || ethtool_state->ring - || ethtool_state->pause || ethtool_state->channels || ethtool_state->eee) + || ethtool_state->pause || ethtool_state->channels || ethtool_state->eee + || ethtool_state->fec_mode != 0) priv->ethtool_state = g_steal_pointer(ðtool_state); } @@ -3124,7 +3316,7 @@ link_properties_fill_from_setting(NMDevice *self, NMPlatformLinkProps *props) NMSettingLink *s_link; gint64 v; - *props = (NMPlatformLinkProps){}; + *props = (NMPlatformLinkProps) {}; s_link = nm_device_get_applied_setting(self, NM_TYPE_SETTING_LINK); if (!s_link) @@ -3336,7 +3528,7 @@ nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source) return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex, source); } -const NML3ConfigData * +NML3ConfigData * nm_device_create_l3_config_data_from_connection(NMDevice *self, NMConnection *connection) { NML3ConfigData *l3cd; @@ -4610,15 +4802,6 @@ _dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, N 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; @@ -4646,16 +4829,25 @@ _dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, N const NML3ConfigData *l3cd; NMDeviceState state = nm_device_get_state(self); + l3cd = nm_l3cfg_get_combined_l3cd(l3cfg, TRUE); if (state >= NM_DEVICE_STATE_IP_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) { /* 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); } + _dev_ipll4_check_fallback(self, l3cd); return; } case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT: + if (notify_data->commit.l3cd_changed) { + g_signal_emit(self, + signals[L3CD_CHANGED], + 0, + notify_data->commit.l3cd_old, + notify_data->commit.l3cd_new); + } + 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); @@ -5635,6 +5827,8 @@ nm_device_get_route_metric_default(NMDeviceType device_type) return 400; case NM_DEVICE_TYPE_MACVLAN: return 410; + case NM_DEVICE_TYPE_IPVLAN: + return 420; case NM_DEVICE_TYPE_BRIDGE: return 425; case NM_DEVICE_TYPE_TUN: @@ -7971,9 +8165,9 @@ sriov_op_queue(NMDevice *self, * grace period we pull the plug and cancel it. */ op = g_slice_new(SriovOp); - *op = (SriovOp){ + *op = (SriovOp) { .sriov_params = - (NMPlatformSriovParams){ + (NMPlatformSriovParams) { .num_vfs = num_vfs, .autoprobe = autoprobe, .eswitch_mode = (_NMSriovEswitchMode) eswitch_mode, @@ -8554,7 +8748,7 @@ port_state_changed(NMDevice *port, /** * nm_device_controller_add_port: * @self: the controller device - * @port: the port device to attach as port + * @port: the port device to attach as port * @configure: pass %TRUE if the port should be configured by the controller, or * %FALSE if it is already configured outside NetworkManager * @@ -10722,6 +10916,25 @@ _dev_ipll4_start(NMDevice *self) nm_l3_ipv4ll_register_new(priv->ipll_data_4.v4.ipv4ll, timeout_msec); } +static void +_dev_ipll4_check_fallback(NMDevice *self, const NML3ConfigData *l3cd_new) +{ + gboolean has_non_ll; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + if (!l3cd_new || priv->ipll_data_4.v4.mode != NM_SETTING_IP4_LL_FALLBACK) { + return; + } + + has_non_ll = nm_l3_config_data_get_flags(l3cd_new) & NM_L3_CONFIG_DAT_FLAGS_HAS_IPV4_NON_LL; + _LOGT_ipll(AF_INET, "%s fallback", has_non_ll ? "cleanup" : "start"); + if (has_non_ll) { + _dev_ipllx_cleanup(self, AF_INET); + } else { + _dev_ipll4_start(self); + } +} + /*****************************************************************************/ static const char * @@ -10963,8 +11176,8 @@ _dev_ipmanual_check_ready(NMDevice *self) static void _dev_ipmanual_start(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; if (priv->ipmanual_data.state_4 != NM_DEVICE_IP_STATE_NONE || priv->ipmanual_data.state_6 != NM_DEVICE_IP_STATE_NONE) @@ -10974,6 +11187,13 @@ _dev_ipmanual_start(NMDevice *self) l3cd = nm_device_create_l3_config_data_from_connection(self, nm_device_get_applied_connection(self)); + + if (_prop_get_ipvx_routed_dns(self, AF_INET) == NM_SETTING_IP_CONFIG_ROUTED_DNS_YES) { + nm_l3_config_data_set_routed_dns(l3cd, AF_INET, TRUE); + } + if (_prop_get_ipvx_routed_dns(self, AF_INET6) == NM_SETTING_IP_CONFIG_ROUTED_DNS_YES) { + nm_l3_config_data_set_routed_dns(l3cd, AF_INET6, TRUE); + } } if (!l3cd) { @@ -11130,6 +11350,8 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d const NML3ConfigData *dhcp_l3cd = priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4)].d; _LOGT_ipdhcp(addr_family, "lease lost"); + _dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_PENDING); + _dev_ip_state_check_async(self, addr_family); if (dhcp_l3cd && nm_l3cfg_remove_config( priv->l3cfg, @@ -11273,7 +11495,8 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) gboolean hostname_is_fqdn; gboolean send_client_id; guint8 dscp; - gboolean dscp_explicit = FALSE; + gboolean dscp_explicit = FALSE; + gboolean ipv6_only_pref = FALSE; client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr, &send_client_id); dscp = _prop_get_ipv4_dhcp_dscp(self, &dscp_explicit); @@ -11292,7 +11515,18 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip); } - config = (NMDhcpClientConfig){ + if (_prop_get_ipv4_dhcp_ipv6_only_preferred(self)) { + if (nm_streq0(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { + _LOGI_ipdhcp( + addr_family, + "not requesting the \"IPv6-only preferred\" option because IPv6 is disabled"); + } else { + _LOGD_ipdhcp(addr_family, "requesting the \"IPv6-only preferred\" option"); + ipv6_only_pref = TRUE; + } + } + + config = (NMDhcpClientConfig) { .addr_family = AF_INET, .l3cfg = nm_device_get_l3cfg(self), .iface = nm_device_get_ip_iface(self), @@ -11300,7 +11534,7 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) .uuid = nm_connection_get_uuid(connection), .hwaddr = hwaddr, .bcast_hwaddr = bcast_hwaddr, - .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip), + .send_hostname = _prop_get_ipvx_dhcp_send_hostname(self, AF_INET), .hostname = hostname, .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET), .client_id = client_id, @@ -11312,11 +11546,12 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) .reject_servers = reject_servers, .v4 = { - .request_broadcast = request_broadcast, - .acd_timeout_msec = _prop_get_ipv4_dad_timeout(self), - .send_client_id = send_client_id, - .dscp = dscp, - .dscp_explicit = dscp_explicit, + .request_broadcast = request_broadcast, + .acd_timeout_msec = _prop_get_ipv4_dad_timeout(self), + .send_client_id = send_client_id, + .dscp = dscp, + .dscp_explicit = dscp_explicit, + .ipv6_only_preferred = ipv6_only_pref, }, .previous_lease = priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4)].d, }; @@ -11333,13 +11568,13 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family) 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){ + config = (NMDhcpClientConfig) { .addr_family = AF_INET6, .l3cfg = nm_device_get_l3cfg(self), .iface = nm_device_get_ip_iface(self), .iface_type_log = nm_device_get_type_desc_for_log(self), .uuid = nm_connection_get_uuid(connection), - .send_hostname = nm_setting_ip_config_get_dhcp_send_hostname(s_ip), + .send_hostname = _prop_get_ipvx_dhcp_send_hostname(self, AF_INET6), .hostname = nm_setting_ip_config_get_dhcp_hostname(s_ip), .hostname_flags = _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6), .client_id = duid, @@ -12629,6 +12864,9 @@ _dev_sysctl_save_ip6_properties(NMDevice *self) if (!ifname) return; + if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) + return; + for (i = 0; i < G_N_ELEMENTS(ip6_properties_to_save); i++) { value = nm_platform_sysctl_ip_conf_get(platform, AF_INET6, ifname, ip6_properties_to_save[i]); @@ -12648,6 +12886,9 @@ _dev_sysctl_restore_ip6_properties(NMDevice *self) gpointer key; gpointer value; + if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) + return; + g_hash_table_iter_init(&iter, priv->ip6_saved_properties); while (g_hash_table_iter_next(&iter, &key, &value)) nm_device_sysctl_ip_conf_set(self, AF_INET6, key, value); @@ -12769,7 +13010,7 @@ get_ip_method_auto(NMDevice *self, int addr_family) } static void -activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family, const char *method) +activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family) { const int IS_IPv4 = NM_IS_IPv4(addr_family); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); @@ -12819,30 +13060,31 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family, const goto out_devip; if (IS_IPv4) { - if (_prop_get_ipv4_link_local(self) == NM_SETTING_IP4_LL_ENABLED) + priv->ipll_data_4.v4.mode = _prop_get_ipv4_link_local(self); + if (priv->ipll_data_4.v4.mode == NM_SETTING_IP4_LL_ENABLED) _dev_ipll4_start(self); - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) + if (nm_streq(priv->ipv4_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)) { + else if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) { /* pass */ - } else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) + } else if (nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) _dev_ipshared4_start(self); - else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) + else if (nm_streq(priv->ipv4_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)) { + else if (nm_streq(priv->ipv4_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)) { + if (nm_streq(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) { 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)) { + } else if (nm_streq(priv->ipv6_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->controller) { @@ -12875,15 +13117,15 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family, const } else { _dev_ipll6_start(self); - if (NM_IN_STRSET(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) + if (NM_IN_STRSET(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) _dev_ipac6_start(self); - else if (NM_IN_STRSET(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) + else if (NM_IN_STRSET(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) _dev_ipshared6_start(self); - else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { + else if (nm_streq(priv->ipv6_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 - nm_assert(NM_IN_STRSET(method, + nm_assert(NM_IN_STRSET(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)); } @@ -12984,8 +13226,6 @@ activate_stage3_ip_config(NMDevice *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. * @@ -13035,17 +13275,17 @@ activate_stage3_ip_config(NMDevice *self) } nm_assert(ifindex <= 0 || priv->fw_state == FIREWALL_STATE_INITIALIZED); - ipv4_method = nm_device_get_effective_ip_config_method(self, AF_INET); - if (nm_streq(ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + priv->ipv4_method = nm_device_get_effective_ip_config_method(self, AF_INET); + if (nm_streq(priv->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); + priv->ipv4_method = klass->get_ip_method_auto(self, AF_INET); } - ipv6_method = nm_device_get_effective_ip_config_method(self, AF_INET6); + priv->ipv6_method = nm_device_get_effective_ip_config_method(self, AF_INET6); if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) { _NMLOG_ip((nm_device_managed_type_is_external(self) - || NM_IN_STRSET(ipv6_method, + || NM_IN_STRSET(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NM_SETTING_IP6_CONFIG_METHOD_DISABLED, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) @@ -13053,9 +13293,9 @@ activate_stage3_ip_config(NMDevice *self) : LOGL_WARN, AF_INET6, "IPv6 not supported by kernel resulting in \"ipv6.method=disabled\""); - ipv6_method = NM_SETTING_IP6_CONFIG_METHOD_DISABLED; - } else if (nm_streq(ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { - ipv6_method = klass->get_ip_method_auto(self, AF_INET6); + priv->ipv6_method = NM_SETTING_IP6_CONFIG_METHOD_DISABLED; + } else if (nm_streq(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { + priv->ipv6_method = klass->get_ip_method_auto(self, AF_INET6); } if (priv->ip_data_4.do_reapply) { @@ -13064,7 +13304,7 @@ activate_stage3_ip_config(NMDevice *self) _cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_KEEP_REAPPLY, - nm_streq(ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)); + nm_streq(priv->ipv4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)); } if (priv->ip_data_6.do_reapply) { _LOGD_ip(AF_INET6, "reapply..."); @@ -13072,7 +13312,7 @@ activate_stage3_ip_config(NMDevice *self) _cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_KEEP_REAPPLY, - nm_streq(ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)); + nm_streq(priv->ipv6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)); } if (priv->state < NM_DEVICE_STATE_IP_CONFIG) { @@ -13103,7 +13343,7 @@ activate_stage3_ip_config(NMDevice *self) if (!nm_device_managed_type_is_external(self) && (!klass->ready_for_ip_config || klass->ready_for_ip_config(self, TRUE))) { if (priv->ipmanual_data.state_6 == NM_DEVICE_IP_STATE_NONE - && !NM_IN_STRSET(ipv6_method, + && !NM_IN_STRSET(priv->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 @@ -13127,8 +13367,8 @@ activate_stage3_ip_config(NMDevice *self) _dev_ipmanual_start(self); } - activate_stage3_ip_config_for_addr_family(self, AF_INET, ipv4_method); - activate_stage3_ip_config_for_addr_family(self, AF_INET6, ipv6_method); + activate_stage3_ip_config_for_addr_family(self, AF_INET); + activate_stage3_ip_config_for_addr_family(self, AF_INET6); } void @@ -13349,6 +13589,9 @@ _dev_ipshared4_spawn_dnsmasq(NMDevice *self) NMConnection *applied; gs_unref_array GArray *conflicts = NULL; gboolean ready; + NMSettingIPConfig *s_ip4 = NULL; + const char *shared_dhcp_range; + int shared_dhcp_lease_time; nm_assert(priv->ipshared_data_4.v4.firewall_config); nm_assert(priv->ipshared_data_4.v4.dnsmasq_state_id == 0); @@ -13394,9 +13637,14 @@ _dev_ipshared4_spawn_dnsmasq(NMDevice *self) break; } + s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG); + shared_dhcp_range = nm_setting_ip_config_get_shared_dhcp_range(s_ip4); + shared_dhcp_lease_time = nm_setting_ip_config_get_shared_dhcp_lease_time(s_ip4); 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, + shared_dhcp_range, + shared_dhcp_lease_time, announce_android_metered, &error)) { _LOGW_ipshared(AF_INET, "could not start dnsmasq: %s", error->message); @@ -13567,8 +13815,11 @@ _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gbool _dev_ipdhcpx_cleanup(self, addr_family, !preserve_dhcp || !keep_reapply, FALSE); - if (!IS_IPv4) + if (IS_IPv4) { + priv->ipll_data_4.v4.mode = NM_SETTING_IP4_LL_DISABLED; + } else { _dev_ipac6_cleanup(self); + } _dev_ipllx_cleanup(self, addr_family); @@ -14125,7 +14376,7 @@ impl_device_reapply(NMDBusObject *obj, } reapply_data = g_slice_new(ReapplyData); - *reapply_data = (ReapplyData){ + *reapply_data = (ReapplyData) { .connection = connection, .version_id = version_id, .reapply_flags = reapply_flags, @@ -14708,6 +14959,37 @@ _dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_da /*****************************************************************************/ +typedef struct { + NMLogDomain log_domain; + NMDevice *device; + gboolean ping_addresses_require_all; + GSource *watch; + GPid pid; + char *binary; + char *address; + guint deadline; +} PingOperation; + +static PingOperation * +ping_operation_new(NMDevice *self, + NMLogDomain log_domain, + const char *address, + const char *ping_binary, + guint ping_timeout, + gboolean ip_ping_addresses_require_all) +{ + PingOperation *ping_op = g_new0(PingOperation, 1); + + ping_op->device = self; + ping_op->log_domain = log_domain; + ping_op->address = g_strdup(address); + ping_op->binary = g_strdup(ping_binary); + ping_op->deadline = ping_timeout + 10; + ping_op->ping_addresses_require_all = ip_ping_addresses_require_all; + + return ping_op; +} + static void ip_check_pre_up(NMDevice *self) { @@ -14730,49 +15012,50 @@ ip_check_pre_up(NMDevice *self) } static void -ip_check_gw_ping_cleanup(NMDevice *self) +cleanup_ping_operation(PingOperation *ping_op) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - - nm_clear_g_source(&priv->gw_ping.watch); - nm_clear_g_source(&priv->gw_ping.timeout); + if (ping_op->watch) { + nm_clear_g_source_inst(&ping_op->watch); + } - if (priv->gw_ping.pid) { - nm_utils_kill_child_async(priv->gw_ping.pid, + if (ping_op->pid) { + nm_utils_kill_child_async(ping_op->pid, SIGTERM, - priv->gw_ping.log_domain, + ping_op->log_domain, "ping", 1000, NULL, NULL); - priv->gw_ping.pid = 0; + ping_op->pid = 0; } - nm_clear_g_free(&priv->gw_ping.binary); - nm_clear_g_free(&priv->gw_ping.address); + nm_clear_g_free(&ping_op->binary); + nm_clear_g_free(&ping_op->address); + + g_free(ping_op); } static gboolean -spawn_ping(NMDevice *self) +spawn_ping_for_operation(NMDevice *self, PingOperation *ping_op) { - 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, + const char *args[] = {ping_op->binary, "-I", nm_device_get_ip_iface(self), "-c", "1", "-w", NULL, - priv->gw_ping.address, + ping_op->address, NULL}; gs_free_error GError *error = NULL; gboolean ret; - args[6] = str_timeout = g_strdup_printf("%u", priv->gw_ping.deadline); - tmp_str = g_strjoinv(" ", (char **) args); - _LOGD(priv->gw_ping.log_domain, "ping: running '%s'", tmp_str); + args[6] = str_timeout = g_strdup_printf("%u", ping_op->deadline); + + tmp_str = g_strjoinv(" ", (char **) args); + _LOGD(ping_op->log_domain, "ping: running '%s'", tmp_str); ret = g_spawn_async("/", (char **) args, @@ -14780,14 +15063,13 @@ spawn_ping(NMDevice *self) G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, - &priv->gw_ping.pid, + &ping_op->pid, &error); - if (!ret) { - _LOGW(priv->gw_ping.log_domain, - "ping: could not spawn %s: %s", - priv->gw_ping.binary, - error->message); + if (ret) { + ping_op->watch = nm_g_child_watch_add_source(ping_op->pid, ip_check_ping_watch_cb, ping_op); + } else { + _LOGD(ping_op->log_domain, "ping: could not spawn %s: %s", ping_op->binary, error->message); } return ret; @@ -14796,16 +15078,19 @@ spawn_ping(NMDevice *self) static gboolean respawn_ping_cb(gpointer user_data) { - NMDevice *self = NM_DEVICE(user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + PingOperation *ping_op = (PingOperation *) user_data; + NMDevice *self = ping_op->device; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - priv->gw_ping.watch = 0; + nm_clear_g_source_inst(&ping_op->watch); - if (spawn_ping(self)) { - priv->gw_ping.watch = g_child_watch_add(priv->gw_ping.pid, ip_check_ping_watch_cb, self); - } else { - ip_check_gw_ping_cleanup(self); - ip_check_pre_up(self); + if (!spawn_ping_for_operation(self, ping_op)) { + cleanup_ping_operation(ping_op); + priv->ping_operations = g_list_remove(priv->ping_operations, ping_op); + + if (g_list_length(priv->ping_operations) == 0) { + ip_check_pre_up(self); + } } return FALSE; @@ -14814,34 +15099,64 @@ 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); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMLogDomain log_domain = priv->gw_ping.log_domain; - gboolean success = FALSE; + PingOperation *ping_op = (PingOperation *) user_data; + NMDevice *self = ping_op->device; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + gboolean success = FALSE; - if (!priv->gw_ping.watch) + if (!ping_op->watch) return; - priv->gw_ping.watch = 0; - priv->gw_ping.pid = 0; + + nm_clear_g_source_inst(&ping_op->watch); + ping_op->pid = 0; if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { - _LOGD(log_domain, "ping: gateway ping succeeded"); + _LOGD(ping_op->log_domain, "ping: ping succeeded on %s", ping_op->address); success = TRUE; } else { - _LOGW(log_domain, "ping: gateway ping failed with error code %d", WEXITSTATUS(status)); + _LOGD(ping_op->log_domain, + "ping: ping failed with error code %d on %s", + WEXITSTATUS(status), + ping_op->address); } - } else - _LOGW(log_domain, "ping: stopped unexpectedly with status %d", status); + } else { + _LOGD(ping_op->log_domain, + "ping: stopped unexpectedly with status %d on %s", + status, + ping_op->address); + } if (success) { - /* We've got connectivity, proceed to pre_up */ - ip_check_gw_ping_cleanup(self); - ip_check_pre_up(self); + if (ping_op->ping_addresses_require_all) { + cleanup_ping_operation(ping_op); + priv->ping_operations = g_list_remove(priv->ping_operations, ping_op); + if (g_list_length(priv->ping_operations) == 0) { + _LOGD(ping_op->log_domain, + "ping: ip-ping-addresses requires all, all ping checks on ip-ping-addresses " + "succeeded"); + if (priv->ping_timeout) + nm_clear_g_source_inst(&priv->ping_timeout); + ip_check_pre_up(self); + } + } else { + nm_assert(priv->ping_operations); + + g_list_free_full(priv->ping_operations, (GDestroyNotify) cleanup_ping_operation); + priv->ping_operations = NULL; + + if (priv->ping_timeout) + nm_clear_g_source_inst(&priv->ping_timeout); + + _LOGD(ping_op->log_domain, + "ping: ip-ping-addresses requires any, one ping check on ip-ping-addresses " + "succeeded"); + ip_check_pre_up(self); + } } else { /* If ping exited with an error it may have returned early, * wait 1 second and restart it */ - priv->gw_ping.watch = g_timeout_add_seconds(1, respawn_ping_cb, self); + ping_op->watch = nm_g_timeout_add_seconds_source(1, respawn_ping_cb, ping_op); } } @@ -14851,39 +15166,31 @@ ip_check_ping_timeout_cb(gpointer user_data) NMDevice *self = NM_DEVICE(user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - priv->gw_ping.timeout = 0; + _LOGW(LOGD_DEVICE, "ping timeout: unreachable gateway or ip-ping-addresses"); - _LOGW(priv->gw_ping.log_domain, "ping: gateway ping timed out"); + if (priv->ping_operations) { + g_list_free_full(priv->ping_operations, (GDestroyNotify) cleanup_ping_operation); + priv->ping_operations = NULL; + } - ip_check_gw_ping_cleanup(self); + if (priv->ping_timeout) + nm_clear_g_source_inst(&priv->ping_timeout); ip_check_pre_up(self); + return FALSE; } static gboolean -start_ping(NMDevice *self, - NMLogDomain log_domain, - const char *binary, - const char *address, - guint timeout) +start_ping(NMDevice *self, PingOperation *ping_op) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - g_return_val_if_fail(priv->gw_ping.watch == 0, FALSE); - g_return_val_if_fail(priv->gw_ping.timeout == 0, FALSE); - - priv->gw_ping.log_domain = log_domain; - priv->gw_ping.address = g_strdup(address); - priv->gw_ping.binary = g_strdup(binary); - priv->gw_ping.deadline = timeout + 10; /* the proper termination is enforced by a timer */ - - if (spawn_ping(self)) { - priv->gw_ping.watch = g_child_watch_add(priv->gw_ping.pid, ip_check_ping_watch_cb, self); - priv->gw_ping.timeout = g_timeout_add_seconds(timeout, ip_check_ping_timeout_cb, self); + if (spawn_ping_for_operation(self, ping_op)) { + priv->ping_operations = g_list_append(priv->ping_operations, ping_op); return TRUE; } - ip_check_gw_ping_cleanup(self); + cleanup_ping_operation(ping_op); return FALSE; } @@ -14893,18 +15200,19 @@ nm_device_start_ip_check(NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMConnection *connection; NMSettingConnection *s_con; - guint timeout = 0; - const char *ping_binary = NULL; + guint gw_ping_timeout = 0; + guint ip_ping_timeout = 0; + const char *ping_binary = NULL; char buf[NM_INET_ADDRSTRLEN]; NMLogDomain log_domain = LOGD_IP4; + gboolean ip_ping_addresses_require_all; + gboolean ping_started = FALSE; /* Shouldn't be any active ping here, since IP_CHECK happens after the * first IP method completes. Any subsequently completing IP method doesn't * get checked. */ - 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->ping_operations == NULL); g_return_if_fail(priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY || priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY); @@ -14913,13 +15221,17 @@ nm_device_start_ip_check(NMDevice *self) s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); - timeout = nm_setting_connection_get_gateway_ping_timeout(s_con); + gw_ping_timeout = nm_setting_connection_get_gateway_ping_timeout(s_con); + ip_ping_addresses_require_all = _prop_get_connection_ip_ping_addresses_require_all(self, s_con); + ip_ping_timeout = nm_setting_connection_get_ip_ping_timeout(s_con); buf[0] = '\0'; - if (timeout) { + if (gw_ping_timeout != 0 && ip_ping_timeout == 0) { const NMPObject *gw; const NML3ConfigData *l3cd; + _LOGD(LOGD_DEVICE, "starting ping gateway..."); + l3cd = priv->l3cfg ? nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE) : NULL; if (!l3cd) { /* pass */ @@ -14940,11 +15252,68 @@ nm_device_start_ip_check(NMDevice *self) } } - if (buf[0]) - start_ping(self, log_domain, ping_binary, buf, timeout); + if (buf[0]) { + PingOperation *ping_op = ping_operation_new(self, + log_domain, + buf, + ping_binary, + gw_ping_timeout, + ip_ping_addresses_require_all); - /* If no ping was started, just advance to pre_up */ - if (!priv->gw_ping.pid) + if (start_ping(self, ping_op)) + ping_started = TRUE; + } + + if (gw_ping_timeout == 0 && ip_ping_timeout != 0) { + const NML3ConfigData *l3cd; + guint i; + GArray *ip_ping_addresses = _nm_setting_connection_get_ip_ping_addresses(s_con); + const char *const *strv = nm_strvarray_get_strv_notempty(ip_ping_addresses, NULL); + + _LOGD(LOGD_DEVICE, "starting ping ip addresses..."); + + l3cd = priv->l3cfg ? nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE) : NULL; + + if (l3cd) { + for (i = 0; strv[i]; i++) { + const char *s = strv[i]; + struct in_addr ipv4_addr; + struct in6_addr ipv6_addr; + + if (priv->ip_data_4.state == NM_DEVICE_IP_STATE_READY + && inet_pton(AF_INET, (const char *) s, &ipv4_addr)) { + ping_binary = nm_utils_find_helper("ping", "/usr/bin/ping", NULL); + log_domain = LOGD_IP4; + } else if (priv->ip_data_6.state == NM_DEVICE_IP_STATE_READY + && inet_pton(AF_INET6, (const char *) s, &ipv6_addr)) { + ping_binary = nm_utils_find_helper("ping6", "/usr/bin/ping6", NULL); + log_domain = LOGD_IP6; + } else + continue; + + if (s[0]) { + PingOperation *ping_op = ping_operation_new(self, + log_domain, + s, + ping_binary, + ip_ping_timeout, + ip_ping_addresses_require_all); + + if (start_ping(self, ping_op)) + ping_started = TRUE; + } + } + } + } + + if (ping_started) { + priv->ping_timeout = + nm_g_timeout_add_seconds_source(gw_ping_timeout ? gw_ping_timeout : ip_ping_timeout, + ip_check_ping_timeout_cb, + self); + } + /* If no ping was started, just advance to pre_up. */ + else ip_check_pre_up(self); } @@ -16403,7 +16772,14 @@ _cancel_activation(NMDevice *self) } _dispatcher_cleanup(self); - ip_check_gw_ping_cleanup(self); + + if (priv->ping_operations) { + g_list_free_full(priv->ping_operations, (GDestroyNotify) cleanup_ping_operation); + priv->ping_operations = NULL; + } + + if (priv->ping_timeout) + nm_clear_g_source_inst(&priv->ping_timeout); _dev_ip_state_cleanup(self, AF_INET, FALSE); _dev_ip_state_cleanup(self, AF_INET6, FALSE); @@ -16629,6 +17005,9 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu priv->promisc_reset = NM_OPTION_BOOL_DEFAULT; } + priv->ipv4_method = NULL; + priv->ipv6_method = NULL; + _cleanup_generic_post(self, reason, cleanup_type); } @@ -16643,6 +17022,9 @@ deactivate_reset_hw_addr(NMDevice *self) static void ip6_managed_setup(NMDevice *self) { + if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) + return; + _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"); @@ -17138,7 +17520,12 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, break; } case NM_DEVICE_STATE_SECONDARIES: - ip_check_gw_ping_cleanup(self); + if (priv->ping_operations) { + g_list_free_full(priv->ping_operations, (GDestroyNotify) cleanup_ping_operation); + priv->ping_operations = NULL; + } + if (priv->ping_timeout) + nm_clear_g_source_inst(&priv->ping_timeout); _LOGD(LOGD_DEVICE, "device entered SECONDARIES state"); break; default: @@ -18382,7 +18769,7 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean resolver = priv->hostname_resolver_x[IS_IPv4]; if (!resolver) { resolver = g_slice_new(HostnameResolver); - *resolver = (HostnameResolver){ + *resolver = (HostnameResolver) { .device = self, .addr_family = addr_family, .state = RESOLVER_WAIT_ADDRESS, @@ -18737,7 +19124,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps nm_assert(priv->type == NM_DEVICE_TYPE_UNKNOWN); priv->type = g_value_get_uint(value); nm_assert(priv->type > NM_DEVICE_TYPE_UNKNOWN); - nm_assert(priv->type <= NM_DEVICE_TYPE_HSR); + nm_assert(priv->type <= NM_DEVICE_TYPE_IPVLAN); break; case PROP_LINK_TYPE: /* construct-only */ @@ -19525,6 +19912,9 @@ nm_device_class_init(NMDeviceClass *klass) G_TYPE_BOOLEAN, 0); + /* Signal "l3cd-changed" indicates that the combined layer-3 configuration + * on the device has changed. It is invoked after the new configuration has + * been committed to kernel. */ signals[L3CD_CHANGED] = g_signal_new(NM_DEVICE_L3CD_CHANGED, G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_FIRST, diff --git a/src/core/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index 59c8f54c..e08b379a 100644 --- a/src/core/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -397,7 +397,7 @@ lldp_neighbor_new(NMLldpNeighbor *neighbor_nm) } neigh = g_slice_new(LldpNeighbor); - *neigh = (LldpNeighbor){ + *neigh = (LldpNeighbor) { .neighbor_nm = nm_lldp_neighbor_ref(neighbor_nm), .chassis_id_type = chassis_id_type, .chassis_id = g_steal_pointer(&s_chassis_id), @@ -522,7 +522,7 @@ lldp_neighbor_to_variant(LldpNeighbor *neigh) if (len <= 6) continue; - /* skip over leading TLV, OUI and subtype */ + /* skip over leading TLV, OUI and subtype */ #if NM_MORE_ASSERTS > 5 { guint8 check_hdr[] = {0xfe | (((len - 2) >> 8) & 0x01), @@ -721,7 +721,7 @@ nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len) g_assert(raw_data); g_assert(raw_len > 0); - lldp_rx = nm_lldp_rx_new(&((NMLldpRXConfig){ + lldp_rx = nm_lldp_rx_new(&((NMLldpRXConfig) { .ifindex = 1, .neighbors_max = MAX_NEIGHBORS, .callback = nmtst_lldp_event_handler, @@ -889,7 +889,7 @@ nm_lldp_listener_new(int ifindex, g_return_val_if_fail(notify_callback, FALSE); self = g_slice_new(NMLldpListener); - *self = (NMLldpListener){ + *self = (NMLldpListener) { .ifindex = ifindex, .notify_callback = notify_callback, .notify_user_data = notify_user_data, @@ -897,7 +897,7 @@ nm_lldp_listener_new(int ifindex, nm_assert(nm_g_main_context_is_thread_default(g_main_context_default())); - lldp_rx = nm_lldp_rx_new(&((NMLldpRXConfig){ + lldp_rx = nm_lldp_rx_new(&((NMLldpRXConfig) { .ifindex = ifindex, .neighbors_max = MAX_NEIGHBORS, .callback = lldp_event_handler, diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 8aeb8718..06a1da15 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -603,7 +603,7 @@ deactivate_async(NMDevice *device, * with a timeout. */ data = g_slice_new(DeactivateData); - *data = (DeactivateData){ + *data = (DeactivateData) { .self = g_object_ref(self), .cancellable = g_object_ref(cancellable), .callback = callback, diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c index 2e8ab717..7eacedb8 100644 --- a/src/core/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -175,7 +175,7 @@ attach_port(NMDevice *device, } data = g_slice_new(AttachPortData); - *data = (AttachPortData){ + *data = (AttachPortData) { .device = g_object_ref(device), .port = g_object_ref(port), .cancellable = g_object_ref(cancellable), @@ -233,7 +233,7 @@ detach_port(NMDevice *device, AttachPortData *data; data = g_slice_new(AttachPortData); - *data = (AttachPortData){ + *data = (AttachPortData) { .device = g_object_ref(device), .port = g_object_ref(port), .cancellable = nm_g_object_ref(cancellable), diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 8e32cff5..528d44d8 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -205,7 +205,7 @@ static void cleanup_check_ready(NMOvsdb *self); /*****************************************************************************/ #define OVSDB_METHOD_PAYLOAD_MONITOR() \ - (&((const OvsdbMethodPayload){ \ + (&((const OvsdbMethodPayload) { \ .monitor = {}, \ })) @@ -214,7 +214,7 @@ static void cleanup_check_ready(NMOvsdb *self); xinterface, \ xbridge_device, \ xinterface_device) \ - (&((const OvsdbMethodPayload){ \ + (&((const OvsdbMethodPayload) { \ .add_interface = \ { \ .bridge = (xbridge), \ @@ -226,7 +226,7 @@ static void cleanup_check_ready(NMOvsdb *self); })) #define OVSDB_METHOD_PAYLOAD_DEL_INTERFACE(xifname) \ - (&((const OvsdbMethodPayload){ \ + (&((const OvsdbMethodPayload) { \ .del_interface = \ { \ .ifname = (char *) NM_CONSTCAST(char, (xifname)), \ @@ -234,7 +234,7 @@ static void cleanup_check_ready(NMOvsdb *self); })) #define OVSDB_METHOD_PAYLOAD_SET_INTERFACE_MTU(xifname, xmtu) \ - (&((const OvsdbMethodPayload){ \ + (&((const OvsdbMethodPayload) { \ .set_interface_mtu = \ { \ .ifname = (char *) NM_CONSTCAST(char, (xifname)), \ @@ -249,7 +249,7 @@ static void cleanup_check_ready(NMOvsdb *self); xexternal_ids_new, \ xother_config_old, \ xother_config_new) \ - (&((const OvsdbMethodPayload){ \ + (&((const OvsdbMethodPayload) { \ .set_reapply = \ { \ .device_type = xdevice_type, \ @@ -420,7 +420,7 @@ ovsdb_call_method(NMOvsdb *self, ovsdb_try_connect(self); call = g_slice_new(OvsdbMethodCall); - *call = (OvsdbMethodCall){ + *call = (OvsdbMethodCall) { .self = self, .call_id = CALL_ID_UNSPEC, .command = command, @@ -1682,7 +1682,7 @@ _strdict_extract(json_t *strdict, GArray **out_array) } v = nm_g_array_append_new(*out_array, NMUtilsNamedValue); - *v = (NMUtilsNamedValue){ + *v = (NMUtilsNamedValue) { .name = g_strdup(key), .value_str = g_strdup(val), }; @@ -1909,7 +1909,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) gs_free char *strtmp2 = NULL; ovs_interface = g_slice_new(OpenvswitchInterface); - *ovs_interface = (OpenvswitchInterface){ + *ovs_interface = (OpenvswitchInterface) { .interface_uuid = g_strdup(key), .name = g_strdup(name), .type = g_strdup(type), @@ -2040,7 +2040,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) gs_free char *strtmp2 = NULL; ovs_port = g_slice_new(OpenvswitchPort); - *ovs_port = (OpenvswitchPort){ + *ovs_port = (OpenvswitchPort) { .port_uuid = g_strdup(key), .name = g_strdup(name), .connection_uuid = g_strdup(connection_uuid), @@ -2161,7 +2161,7 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) gs_free char *strtmp2 = NULL; ovs_bridge = g_slice_new(OpenvswitchBridge); - *ovs_bridge = (OpenvswitchBridge){ + *ovs_bridge = (OpenvswitchBridge) { .bridge_uuid = g_strdup(key), .name = g_strdup(name), .connection_uuid = g_strdup(connection_uuid), @@ -2905,7 +2905,7 @@ ovsdb_call_new(NMOvsdbCallback callback, gpointer user_data) OvsdbCall *call; call = g_slice_new(OvsdbCall); - *call = (OvsdbCall){ + *call = (OvsdbCall) { .callback = callback, .user_data = user_data, }; diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index a4c77f7f..40779c89 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -130,8 +130,7 @@ complete_connection(NMDevice *device, NULL, _("Team connection"), "team", - NULL, - TRUE); + NULL); _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TEAM); diff --git a/src/core/devices/wifi/nm-device-iwd-p2p.c b/src/core/devices/wifi/nm-device-iwd-p2p.c index fadc6722..184c8ec5 100644 --- a/src/core/devices/wifi/nm-device-iwd-p2p.c +++ b/src/core/devices/wifi/nm-device-iwd-p2p.c @@ -301,8 +301,7 @@ complete_connection(NMDevice *device, setting_name, setting_name, NULL, - NULL, - TRUE); + NULL); return TRUE; } diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index d6e3ed08..fa6e2f9d 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -275,7 +275,7 @@ ap_from_network(NMDeviceIwd *self, ssid = g_bytes_new(name, NM_MIN(32u, strlen(name))); - bss_info = (NMSupplicantBssInfo){ + bss_info = (NMSupplicantBssInfo) { .bss_path = bss_path, .last_seen_msec = last_seen_msec, .bssid_valid = TRUE, @@ -1074,8 +1074,7 @@ complete_connection(NMDevice *device, ssid_utf8, ssid_utf8, NULL, - NULL, - TRUE); + NULL); if (hidden) g_object_set(s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL); @@ -3602,7 +3601,7 @@ nm_device_iwd_parse_netconfig(NMDeviceIwd *self, int addr_family, GVariantIter * preferred_lifetime = valid_lifetime; if (addr_family == AF_INET) { - a.a4 = (NMPlatformIP4Address){ + a.a4 = (NMPlatformIP4Address) { .address = addr_bin.addr4, .peer_address = addr_bin.addr4, .plen = plen, @@ -3614,7 +3613,7 @@ nm_device_iwd_parse_netconfig(NMDeviceIwd *self, int addr_family, GVariantIter * .broadcast_address = bcast_bin.addr4, }; } else { - a.a6 = (NMPlatformIP6Address){ + a.a6 = (NMPlatformIP6Address) { .address = addr_bin.addr6, .plen = 128, .timestamp = (valid_lifetime != NM_PLATFORM_LIFETIME_PERMANENT) ? timestamp : 0, @@ -3703,7 +3702,7 @@ nm_device_iwd_parse_netconfig(NMDeviceIwd *self, int addr_family, GVariantIter * } if (addr_family == AF_INET) { - r.r4 = (NMPlatformIP4Route){ + r.r4 = (NMPlatformIP4Route) { .network = dst_addr_str ? dst_addr_bin.addr4 : 0, .plen = dst_addr_str ? dst_plen : 0, .gateway = router_str ? router_bin.addr4 : 0, @@ -3712,7 +3711,7 @@ nm_device_iwd_parse_netconfig(NMDeviceIwd *self, int addr_family, GVariantIter * nm_platform_route_scope_inv(router_str ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK), }; } else { - r.r6 = (NMPlatformIP6Route){ + r.r6 = (NMPlatformIP6Route) { .network = dst_addr_str ? dst_addr_bin.addr6 : nm_ip_addr_zero.addr6, .plen = dst_addr_str ? dst_plen : 0, .gateway = router_str ? router_bin.addr6 : nm_ip_addr_zero.addr6, @@ -3739,7 +3738,7 @@ nm_device_iwd_parse_netconfig(NMDeviceIwd *self, int addr_family, GVariantIter * if (inet_pton(addr_family, str_value, &dns_bin) != 1) goto param_error; - nm_l3_config_data_add_nameserver_detail(l3cd, addr_family, &dns_bin, NULL); + nm_l3_config_data_add_nameserver_addr(l3cd, addr_family, &dns_bin); nm_l3_config_data_set_dns_priority(l3cd, addr_family, NM_DNS_PRIORITY_DEFAULT_NORMAL); } } diff --git a/src/core/devices/wifi/nm-device-olpc-mesh.c b/src/core/devices/wifi/nm-device-olpc-mesh.c index 8e1e779b..b62dc311 100644 --- a/src/core/devices/wifi/nm-device-olpc-mesh.c +++ b/src/core/devices/wifi/nm-device-olpc-mesh.c @@ -111,8 +111,7 @@ complete_connection(NMDevice *device, NULL, _("Mesh"), NULL, - NULL, - FALSE); /* No IPv6 by default */ + NULL); return TRUE; } diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index f06383b1..957a2df6 100644 --- a/src/core/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -319,8 +319,7 @@ complete_connection(NMDevice *device, setting_name, setting_name, NULL, - NULL, - TRUE); + NULL); return TRUE; } diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index ea65499e..06eee142 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -340,7 +340,7 @@ _scan_request_ssids_track(NMDeviceWifiPrivate *priv, const GPtrArray *ssids) d = g_hash_table_lookup(priv->scan_request_ssids_hash, &ssid); if (!d) { d = g_slice_new(ScanRequestSsidData); - *d = (ScanRequestSsidData){ + *d = (ScanRequestSsidData) { .lst = C_LIST_INIT(d->lst), .timestamp_msec = now_msec, .ssid = g_bytes_ref(ssid), @@ -1296,8 +1296,7 @@ complete_connection(NMDevice *device, ssid_utf8, ssid_utf8, NULL, - nm_setting_wireless_get_mac_address(s_wifi) ? NULL : nm_device_get_iface(device), - TRUE); + nm_setting_wireless_get_mac_address(s_wifi) ? NULL : nm_device_get_iface(device)); if (hidden) g_object_set(s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL); diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index 8a8d062f..332352ab 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -1577,19 +1577,17 @@ ip_config_to_iwd_config(int addr_family, GKeyFile *file, NMSettingIPConfig *s_ip if (num) { nm_str_buf_reset(&strbuf); for (i = 0; i < num; i++) { - char sbuf[NM_INET_ADDRSTRLEN]; - NMIPAddr a; - - if (!nm_utils_dnsname_parse_assert(addr_family, - nm_setting_ip_config_get_dns(s_ip, i), - NULL, - &a, - NULL)) + char addrstr[NM_INET_ADDRSTRLEN]; + + if (!nm_dns_uri_parse_plain(addr_family, + nm_setting_ip_config_get_dns(s_ip, i), + addrstr, + NULL)) continue; if (strbuf.len > 0) nm_str_buf_append_c(&strbuf, ' '); - nm_str_buf_append(&strbuf, nm_inet_ntop(addr_family, &a, sbuf)); + nm_str_buf_append(&strbuf, addrstr); } /* It doesn't matter whether we add the DNS under [IPv4] or [IPv6] * except that with method=auto the list will override the diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index c03446b9..018e5306 100644 --- a/src/core/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -668,6 +668,8 @@ connect_context_step(NMModemBroadband *self) NMSettingGsm *s_gsm = nm_connection_get_setting_gsm(ctx->connection); const char *apn = nm_setting_gsm_get_initial_eps_apn(s_gsm); gboolean do_config = nm_setting_gsm_get_initial_eps_config(s_gsm); + const char *username = nm_setting_gsm_get_initial_eps_username(s_gsm); + const char *password = nm_setting_gsm_get_initial_eps_password(s_gsm); /* assume do_config is true if an APN is set */ if (apn || do_config) { @@ -690,9 +692,28 @@ connect_context_step(NMModemBroadband *self) /* do nothing */ break; } - if (apn) - mm_bearer_properties_set_apn(config, apn); + if (apn) { + MMBearerAllowedAuth allowed_auth = MM_BEARER_ALLOWED_AUTH_UNKNOWN; + mm_bearer_properties_set_apn(config, apn); + mm_bearer_properties_set_user(config, username); + mm_bearer_properties_set_password(config, password); + + if (nm_setting_gsm_get_initial_eps_noauth(s_gsm)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_NONE; + if (!nm_setting_gsm_get_initial_eps_refuse_pap(s_gsm)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_PAP; + if (!nm_setting_gsm_get_initial_eps_refuse_chap(s_gsm)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_CHAP; + if (!nm_setting_gsm_get_initial_eps_refuse_mschap(s_gsm)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_MSCHAP; + if (!nm_setting_gsm_get_initial_eps_refuse_mschapv2(s_gsm)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_MSCHAPV2; + if (!nm_setting_gsm_get_initial_eps_refuse_eap(s_gsm)) + allowed_auth |= MM_BEARER_ALLOWED_AUTH_EAP; + + mm_bearer_properties_set_allowed_auth(config, allowed_auth); + } /* * Setting the initial EPS bearer settings is a no-op in * ModemManager if the desired configuration is already active. @@ -896,8 +917,7 @@ complete_connection(NMModem *modem, NULL, _("GSM connection"), NULL, - NULL, - FALSE); /* No IPv6 yet by default */ + NULL); return TRUE; } @@ -917,8 +937,7 @@ complete_connection(NMModem *modem, NULL, _("CDMA connection"), NULL, - iface, - FALSE); /* No IPv6 yet by default */ + iface); return TRUE; } @@ -1116,7 +1135,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho ifindex, NM_IP_CONFIG_SOURCE_WWAN); - address = (NMPlatformIP4Address){ + address = (NMPlatformIP4Address) { .address = address_network, .peer_address = address_network, .plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config), @@ -1127,7 +1146,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho _LOGI(" address %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf))); - route = (NMPlatformIP4Route){ + route = (NMPlatformIP4Route) { .rt_source = NM_IP_CONFIG_SOURCE_WWAN, .gateway = gw, .table_any = TRUE, @@ -1141,7 +1160,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config); for (i = 0; dns && dns[i]; i++) { if (nm_inet_parse_bin(AF_INET, dns[i], NULL, &address_network) && address_network > 0) { - nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET, &address_network, NULL); + nm_l3_config_data_add_nameserver_addr(l3cd, AF_INET, &address_network); _LOGI(" DNS %s", dns[i]); } } @@ -1193,7 +1212,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho do_auto = TRUE; if (address_string) { - address = (NMPlatformIP6Address){}; + address = (NMPlatformIP6Address) {}; if (!inet_pton(AF_INET6, address_string, &address.address)) { g_set_error(&error, @@ -1260,7 +1279,7 @@ stage3_ip_config_start(NMModem *modem, int addr_family, NMModemIPMethod ip_metho struct in6_addr addr; if (inet_pton(AF_INET6, dns[i], &addr)) { - nm_l3_config_data_add_nameserver_detail(l3cd, AF_INET6, &addr, NULL); + nm_l3_config_data_add_nameserver_addr(l3cd, AF_INET6, &addr); _LOGI(" DNS %s", dns[i]); } } diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index 3e0bbd48..80f966f1 100644 --- a/src/core/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -1256,7 +1256,7 @@ handle_settings(NMModemOfono *self, GVariant *v_dict) goto out; } - address = (NMPlatformIP4Address){ + address = (NMPlatformIP4Address) { .ifindex = ifindex, .address = address_network, .addr_source = NM_IP_CONFIG_SOURCE_WWAN, @@ -1315,7 +1315,7 @@ handle_settings(NMModemOfono *self, GVariant *v_dict) } any_good = TRUE; _LOGI("DNS: %s", array[i]); - nm_l3_config_data_add_nameserver_detail(priv->l3cd_4, AF_INET, &address_network, NULL); + nm_l3_config_data_add_nameserver_addr(priv->l3cd_4, AF_INET, &address_network); } if (!any_good) { _LOGW("Settings: 'DomainNameServers': none specified"); diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c index 23e7de4a..c4852ea2 100644 --- a/src/core/devices/wwan/nm-modem.c +++ b/src/core/devices/wwan/nm-modem.c @@ -1064,7 +1064,7 @@ nm_modem_act_stage2_config(NMModem *self, NMDevice *device, NMDeviceStateReason else baud_override = 0; - priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig){ + priv->ppp_mgr = nm_ppp_mgr_start(&((const NMPppMgrConfig) { .netns = nm_device_get_netns(device), .parent_iface = priv->data_port, .callback = _ppp_mgr_callback, -- cgit 1.3.0-6-gf8a5