diff -pruN 1.52.0-1/debian/10-dns-resolved.conf 1.52.0-1ubuntu1/debian/10-dns-resolved.conf
--- 1.52.0-1/debian/10-dns-resolved.conf	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/10-dns-resolved.conf	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,5 @@
+[main]
+# We need to specify "dns=systemd-resolved" as for the time being our
+# /etc/resolv.conf points to resolvconf's generated file instead of
+# systemd-resolved's, so the auto-detection does not work.
+dns=systemd-resolved
diff -pruN 1.52.0-1/debian/10-globally-managed-devices.conf 1.52.0-1ubuntu1/debian/10-globally-managed-devices.conf
--- 1.52.0-1/debian/10-globally-managed-devices.conf	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/10-globally-managed-devices.conf	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,2 @@
+[keyfile]
+unmanaged-devices=*,except:type:wifi,except:type:gsm,except:type:cdma
diff -pruN 1.52.0-1/debian/20-connectivity-ubuntu.conf 1.52.0-1ubuntu1/debian/20-connectivity-ubuntu.conf
--- 1.52.0-1/debian/20-connectivity-ubuntu.conf	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/20-connectivity-ubuntu.conf	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,2 @@
+[connectivity]
+uri=http://connectivity-check.ubuntu.com./
diff -pruN 1.52.0-1/debian/NetworkManager.conf 1.52.0-1ubuntu1/debian/NetworkManager.conf
--- 1.52.0-1/debian/NetworkManager.conf	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/NetworkManager.conf	2025-03-03 17:49:02.000000000 +0000
@@ -3,3 +3,6 @@ plugins=ifupdown,keyfile
 
 [ifupdown]
 managed=false
+
+[device]
+wifi.scan-rand-mac-address=no
diff -pruN 1.52.0-1/debian/changelog 1.52.0-1ubuntu1/debian/changelog
--- 1.52.0-1/debian/changelog	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/changelog	2025-03-03 17:49:02.000000000 +0000
@@ -1,3 +1,63 @@
+network-manager (1.52.0-1ubuntu1) plucky; urgency=medium
+
+  [ Jeremy Bícha ]
+  * Merge with Debian. Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+  [ Lukas Märdian ]
+  * Fix FTBFS on i386 (LP: #2098902)
+    - d/p/n/keyfile-update-test-for-expected-netplan-output.patch
+  * d/t/network_test_base.py: split into base.py and base_wifi.py for veth/wifi
+  * d/t/{control,nm-eth.py}: Isolate containerized nm-eth.py tests
+  * d/tests: Rename nm.py -> nm-wifi.py, nm_netplan.py -> nm-netplan.py
+  * d/t/control,{nm-wifi,nm-netplan,wpa-dhcp}.py: Utilize new classes, clean up
+    Trimming non-wifi code from nm.py (it was moved to nm-eth.py)
+  * d/t/control: Skip WiFi tests on containers
+
+ -- Jeremy Bícha <jbicha@ubuntu.com>  Mon, 03 Mar 2025 12:49:02 -0500
+
 network-manager (1.52.0-1) experimental; urgency=medium
 
   * New upstream version 1.52.0
@@ -6,6 +66,56 @@ network-manager (1.52.0-1) experimental;
 
  -- Michael Biebl <biebl@debian.org>  Fri, 28 Feb 2025 18:58:44 +0100
 
+network-manager (1.51.90-1ubuntu1) plucky; urgency=medium
+
+  * Merge with Debian. Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+  * Add simple patch to update test for our netplan backend
+
+ -- Jeremy Bícha <jbicha@ubuntu.com>  Wed, 19 Feb 2025 15:16:39 -0500
+
 network-manager (1.51.90-1) experimental; urgency=medium
 
   * New upstream version 1.51.90 (1.52 rc1)
@@ -34,6 +144,76 @@ network-manager (1.50.1-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 25 Dec 2024 21:01:45 +0100
 
+network-manager (1.50.0-1ubuntu3) plucky; urgency=medium
+
+  * d/t/control: Add polkitd test-dependency for urfkill-integration
+  * d/t/nm.py: Use non-deprecated deactivate_connection_async
+  * d/t/nm.py: Log proper addCleanup 'FAIL' message
+  * d/t/nm.py: Drop deprecated dhclient hack
+  * d/t/{network_test_base,nm}.py: Use sd-networkd for mgmt network
+  * d/t/nm_netplan: Fix YAMl file permissions
+  * d/t/control: rename d/t/wpa-dhcp.py
+  * d/t/wpa-dhcp.py: Use dhcpcd-base instead of deprecated dhclient
+  * d/t/control,network_test_base.py: Drop deprecated ISC dhclient
+
+ -- Lukas Märdian <slyon@ubuntu.com>  Wed, 22 Jan 2025 12:54:42 +0100
+
+network-manager (1.50.0-1ubuntu2) plucky; urgency=medium
+
+  * Rebuild with the new ppp version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 25 Nov 2024 23:07:08 +0100
+
+network-manager (1.50.0-1ubuntu1) plucky; urgency=medium
+
+  * Merge from Debian unstable (LP: #2087981). Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests (urfkill-integration, wpa-dhclient,
+      killswitches-no-urfkill)
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+ -- Alessandro Astone <alessandro.astone@canonical.com>  Tue, 12 Nov 2024 15:34:49 +0100
+
 network-manager (1.50.0-1) unstable; urgency=medium
 
   * New upstream version 1.50.0
@@ -73,6 +253,68 @@ network-manager (1.48.10-1) unstable; ur
 
  -- Michael Biebl <biebl@debian.org>  Mon, 26 Aug 2024 16:35:44 +0200
 
+network-manager (1.48.8-1ubuntu3) oracular; urgency=medium
+
+  * d/control: Avoid calling into half installed/upgraded Netplan (LP: #2033259)
+
+ -- Lukas Märdian <slyon@ubuntu.com>  Thu, 12 Sep 2024 18:01:03 +0200
+
+network-manager (1.48.8-1ubuntu2) oracular; urgency=medium
+
+  * Update netplan test, fixup one master->controller change
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Wed, 14 Aug 2024 15:58:54 +0200
+
+network-manager (1.48.8-1ubuntu1) oracular; urgency=medium
+
+  * Merge from Debian unstable. Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests (urfkill-integration, wpa-dhclient,
+      killswitches-no-urfkill)
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Mon, 12 Aug 2024 14:07:09 +0200
+
 network-manager (1.48.8-1) unstable; urgency=medium
 
   * New upstream version 1.48.8
@@ -80,6 +322,56 @@ network-manager (1.48.8-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Fri, 09 Aug 2024 20:53:23 +0200
 
+network-manager (1.48.6-1ubuntu1) oracular; urgency=medium
+
+  * Merge from Debian unstable. Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests (urfkill-integration, wpa-dhclient,
+      killswitches-no-urfkill)
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Mon, 29 Jul 2024 10:54:25 +0200
+
 network-manager (1.48.6-1) unstable; urgency=medium
 
   * New upstream version 1.48.6
@@ -87,6 +379,56 @@ network-manager (1.48.6-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Fri, 26 Jul 2024 15:21:36 +0200
 
+network-manager (1.48.4-1ubuntu1) oracular; urgency=low
+
+  * Merge from Debian unstable. Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests (urfkill-integration, wpa-dhclient,
+      killswitches-no-urfkill)
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Mon, 08 Jul 2024 13:11:44 +0200
+
 network-manager (1.48.4-1) unstable; urgency=medium
 
   * New upstream version 1.48.4
@@ -94,6 +436,56 @@ network-manager (1.48.4-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Fri, 05 Jul 2024 19:10:23 +0200
 
+network-manager (1.48.2-1ubuntu1) oracular; urgency=medium
+
+  * Merge from Debian unstable. Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests (urfkill-integration, wpa-dhclient,
+      killswitches-no-urfkill)
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Tue, 25 Jun 2024 11:25:31 +0200
+
 network-manager (1.48.2-1) unstable; urgency=medium
 
   * New upstream version 1.48.2
@@ -101,6 +493,63 @@ network-manager (1.48.2-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Mon, 24 Jun 2024 15:02:02 +0200
 
+network-manager (1.48.0-1ubuntu3) oracular; urgency=medium
+
+  * Add changes from Lukas Märdian of never uploaded 1.46.0-1ubuntu2 version:
+    - d/p/netplan: Refresh buildsystem patch for config.h.meson compat
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Mon, 24 Jun 2024 12:55:37 +0200
+
+network-manager (1.48.0-1ubuntu2) oracular; urgency=low
+
+  * Merge from Debian unstable. Remaining changes:
+    - d/{control,rules,patches}: Prepare libnetplan build (non i386)
+      + also add yaml dependency, needed for netplan
+    - d/p/netplan: Add libnetplan backend integration patch
+    - d/t/nm.py: Add autopkgtests when Netplan is in use
+    - d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+    - debian/control:
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - d/control: Add network-manager-config-connectivity-ubuntu package
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests (urfkill-integration, wpa-dhclient,
+      killswitches-no-urfkill)
+    - d/{source_network-manager.py,network-manager.install,
+      network-manager.links}: Add apport hook
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+    - d/network-manager.preinst: backup previous configuration automatically
+    - d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org>  Fri, 21 Jun 2024 10:21:12 +0200
+
 network-manager (1.48.0-1) unstable; urgency=medium
 
   * New upstream version 1.48.0
@@ -151,6 +600,19 @@ network-manager (1.46.0-2) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Thu, 25 Apr 2024 19:26:12 +0200
 
+network-manager (1.46.0-1ubuntu2) noble; urgency=medium
+
+  * debian/tests/control: add Depends: python3-gi for nm_netplan.py
+    (LP: #2060221)
+
+ -- Nick Rosbrook <enr0n@ubuntu.com>  Thu, 04 Apr 2024 15:11:48 -0400
+
+network-manager (1.46.0-1ubuntu1) noble; urgency=medium
+
+  * Update to the current stable version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Wed, 03 Apr 2024 11:39:10 +0200
+
 network-manager (1.46.0-1) unstable; urgency=medium
 
   * New upstream version 1.46.0
@@ -168,6 +630,14 @@ network-manager (1.45.91-1) experimental
 
  -- Michael Biebl <biebl@debian.org>  Tue, 13 Feb 2024 22:39:30 +0100
 
+network-manager (1.45.90-1ubuntu1) noble; urgency=medium
+
+  * Merge with Debian.
+  * debian/patches/git_valid_gkeyfile.patch:
+    - cherrypick an upstream change to fix a test issue with glib 2.79
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 12 Feb 2024 16:17:33 +0100
+
 network-manager (1.45.90-1) experimental; urgency=medium
 
   * New upstream version 1.45.90 (1.46 rc1)
@@ -177,6 +647,19 @@ network-manager (1.45.90-1) experimental
 
  -- Michael Biebl <biebl@debian.org>  Thu, 25 Jan 2024 10:32:43 +0100
 
+network-manager (1.44.2-7ubuntu2) noble; urgency=medium
+
+  * debian/tests: Clearly mark regular expressions, to avoid SyntaxWarning.
+    This fixes autopkgtests on Python3.12, failing due to stderr output.
+
+ -- Lukas Märdian <slyon@ubuntu.com>  Mon, 12 Feb 2024 15:08:34 +0100
+
+network-manager (1.44.2-7ubuntu1) noble; urgency=medium
+
+  * Merge with Debian.
+
+ -- Jeremy Bícha <jbicha@ubuntu.com>  Thu, 04 Jan 2024 09:08:35 -0500
+
 network-manager (1.44.2-7) unstable; urgency=medium
 
   [ Simon McVittie ]
@@ -248,6 +731,36 @@ network-manager (1.44.2-2) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 18 Oct 2023 14:24:23 +0200
 
+network-manager (1.44.2-1ubuntu2) noble; urgency=medium
+
+  [ Lukas Märdian ]
+  * network-manager.postinst: Skip unknown connection profiles (LP: #2039503)
+  * d/network-manager.postinst: Drop reboot notification (LP: #2040292)
+
+  [ Danilo Egea Gondolfo ]
+  * debian/tests/nm_netplan.py
+    Start Network Manager via systemd. The .service unit file sets
+    ProtectSystem to true and we want to run the Netplan tests with this
+    restriction enabled.
+  * d/p/netplan/0003-Allow-the-NetworkManager-daemon-to-write-to-lib-netp.patch
+    Allow-list /usr/lib/netplan so libnetplan can open files from that
+    directory with writing permission. See LP: #2040153
+  * debian/tests/control
+    Add all the dependencies required by the nm_netplan.py tests.
+  * debian/tests/network_test_base.py.
+    Increase the waiting time between creating a veth pair and reading their
+    MAC addresses. On arm64, the system is taking longer to change the MAC
+    after creation, leading to failures due to differences in the expected
+    and current MAC addresses. See LP: #2023183
+
+ -- Lukas Märdian <slyon@ubuntu.com>  Thu, 26 Oct 2023 11:48:18 +0200
+
+network-manager (1.44.2-1ubuntu1) mantic; urgency=medium
+
+  * Merge with Debian (LP: #2038439)
+
+ -- Jeremy Bícha <jbicha@ubuntu.com>  Wed, 04 Oct 2023 09:40:22 -0400
+
 network-manager (1.44.2-1) unstable; urgency=medium
 
   * New upstream version 1.44.2
@@ -255,6 +768,28 @@ network-manager (1.44.2-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 04 Oct 2023 12:09:39 +0200
 
+network-manager (1.44.0-1ubuntu2) mantic; urgency=medium
+
+  * d/t/{nm.py,nm_netplan.py,network_test_base.py} (LP: #2033391):
+    - Wait until NM is ready before starting tests
+    - Add a delay loop checking if NM is already on-line before running each
+      test.
+  * d/t/nm.py: remove expectedFailure from both tests in Hotplug.
+    - It's not clear why they were expected to fail. With NM 1.44.0 they are passing.
+    - As this class states that the APs are set up with NM already running, in
+      test_auto_detect_ap() self.start_nm() was moved to run before
+      self.setup_ap() and the assert was fixed to get the actual gobject data.
+
+ -- Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>  Wed, 30 Aug 2023 10:09:50 +0100
+
+network-manager (1.44.0-1ubuntu1) mantic; urgency=medium
+
+  * Resynchronize on Debian to the current stable version
+    - Patches refreshed
+  * Remove erroneous symbol added in 1.42.8-1
+
+ -- Nathan Pratta Teodosio <nathan.teodosio@canonical.com>  Thu, 10 Aug 2023 15:40:38 +0200
+
 network-manager (1.44.0-1) unstable; urgency=medium
 
   * New upstream version 1.44.0
@@ -265,12 +800,33 @@ network-manager (1.44.0-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 09 Aug 2023 22:22:22 +0200
 
+network-manager (1.42.8-1ubuntu1) UNRELEASED; urgency=medium
+
+  * Resynchronize on Debian to the current stable version
+  * debian/libnm0.symbols:
+    - updated symbols for the new version
+
+ -- Nathan Pratta Teodosio <nathan.teodosio@canonical.com>  Wed, 09 Aug 2023 16:08:26 +0200
+
 network-manager (1.42.8-1) unstable; urgency=medium
 
   * New upstream version 1.42.8
 
  -- Michael Biebl <biebl@debian.org>  Wed, 28 Jun 2023 15:22:30 +0200
 
+network-manager (1.42.6-2ubuntu2) mantic; urgency=medium
+
+  * Remove isc-dhcp-client from Depends
+    Unless explicitly configured otherwise the internal DHCP client is used.
+
+ -- Benjamin Drung <bdrung@ubuntu.com>  Tue, 18 Jul 2023 10:51:11 +0200
+
+network-manager (1.42.6-2ubuntu1) mantic; urgency=medium
+
+  * Resynchronize on Debian to the current stable version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Thu, 22 Jun 2023 12:26:23 +0200
+
 network-manager (1.42.6-2) unstable; urgency=medium
 
   * Stop installing deprecated polkit pkla file.
@@ -287,6 +843,74 @@ network-manager (1.42.6-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Mon, 12 Jun 2023 14:48:14 +0200
 
+network-manager (1.42.4-1ubuntu7) mantic; urgency=medium
+
+  [ Michael Biebl ]
+  * Use Build-Depends on polkitd and libpolkit-gobject-1-dev for polkit.its
+    (Closes: #1025606)
+
+  [ Danilo Egea Gondolfo ]
+  * d/t/control: Add easy-rsa as a test dependency
+  * d/t/nm.py: generalize Wifi auth configuration.
+    The idea is to make is easier to implement tests using different
+    authentication methods.
+  * d/t/nm.py: implement WPA-EAP 802.1x tests.
+    These tests are related to an issue in Netplan but they are also useful
+    for network-manager itself. See LP#2016625
+  * d/t/nm_netplan.py: add new test cases for ip-tunnel and wireguard
+    connections, using Netplan integration. See LP#2016473
+
+ -- Lukas Märdian <slyon@ubuntu.com>  Tue, 20 Jun 2023 12:07:12 +0200
+
+network-manager (1.42.4-1ubuntu5) mantic; urgency=medium
+
+  * d/network-manager.postinst: fix netplan migration logic.
+    The "continue" is being executed in a subshell so it's not skipping the
+    next commands. It will fail if Network Manager is not running. See LP: #2022023
+  * d/network-manager.preinst: use /var/lib/NetworkManager for backups
+    /root is not a system directory so we shouldn't use it. It might not
+    even exist or the package manager might run in a sandbox and not have
+    access to it. See LP: #2021937
+
+ -- Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>  Thu, 01 Jun 2023 15:17:57 +0100
+
+network-manager (1.42.4-1ubuntu4) mantic; urgency=medium
+
+  * d/t/nm_netplan.py:openvpn: set a metric for the extra default route.
+    With a higher metric the route shouldn't be selected over the main one.
+    Also, use the same subnet already used by the nm.py tests.
+
+ -- Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>  Thu, 25 May 2023 11:00:31 +0100
+
+network-manager (1.42.4-1ubuntu3) mantic; urgency=medium
+
+  * Upload netplan integration to the Ubuntu archive, details available on
+    https://discourse.ubuntu.com/t/call-for-testing-networkmanager-yaml-settings
+
+  [ Lukas Märdian ]
+  * d/{control,rules,patches}: Prepare libnetplan build (non i386)
+  * debian/patches/netplan: Add libnetplan backend integration patch
+  * d/network-manager.preinst: backup previous configuration automatically
+  * d/network-manager.postinst: Trigger Netplan migration on install/upgrade
+
+  [ Danilo Egea Gondolfo ]
+  * d/t/nm.py: Fix autopkgtests when Netplan is in use
+  * d/t/nm_netplan.py: Add autopkgtests for the netplan integration
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 15 May 2023 13:30:31 +0200
+
+network-manager (1.42.4-1ubuntu2) lunar; urgency=medium
+
+  * d/t/nm.py: Fix autopkgtests with NM-1.42's 'lo' connection (LP: #2009543)
+
+ -- Lukas Märdian <slyon@ubuntu.com>  Tue, 28 Mar 2023 15:13:56 +0200
+
+network-manager (1.42.4-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian to the current stable version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Thu, 23 Mar 2023 21:31:09 +0100
+
 network-manager (1.42.4-1) unstable; urgency=medium
 
   * New upstream version 1.42.4
@@ -304,6 +928,49 @@ network-manager (1.42.2-2) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Fri, 03 Mar 2023 17:57:30 +0100
 
+network-manager (1.42.2-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Thu, 23 Feb 2023 18:14:55 -0500
+
 network-manager (1.42.2-1) unstable; urgency=medium
 
   * New upstream version 1.42.2
@@ -312,6 +979,49 @@ network-manager (1.42.2-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Thu, 23 Feb 2023 17:53:42 +0100
 
+network-manager (1.42.0-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 14 Feb 2023 10:06:44 -0500
+
 network-manager (1.42.0-1) unstable; urgency=medium
 
   * New upstream version 1.42.0
@@ -321,18 +1031,147 @@ network-manager (1.42.0-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Fri, 10 Feb 2023 17:38:16 +0100
 
+network-manager (1.40.12-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Thu, 26 Jan 2023 16:57:14 -0500
+
 network-manager (1.40.12-1) unstable; urgency=medium
 
   * New upstream version 1.40.12
 
  -- Michael Biebl <biebl@debian.org>  Thu, 26 Jan 2023 21:54:37 +0100
 
+network-manager (1.40.10-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Fri, 13 Jan 2023 15:22:40 -0500
+
 network-manager (1.40.10-1) unstable; urgency=medium
 
   * New upstream version 1.40.10
 
  -- Michael Biebl <biebl@debian.org>  Wed, 11 Jan 2023 16:24:40 +0100
 
+network-manager (1.40.8-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Wed, 04 Jan 2023 18:29:41 -0500
+
 network-manager (1.40.8-1) unstable; urgency=medium
 
   * Add lintian override for source-is-missing false positive
@@ -344,6 +1183,49 @@ network-manager (1.40.8-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Mon, 19 Dec 2022 11:30:35 +0100
 
+network-manager (1.40.6-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Fri, 02 Dec 2022 16:31:46 -0500
+
 network-manager (1.40.6-1) unstable; urgency=medium
 
   * New upstream version 1.40.6
@@ -354,6 +1236,57 @@ network-manager (1.40.6-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 30 Nov 2022 22:59:25 +0100
 
+network-manager (1.40.4-1ubuntu2) lunar; urgency=medium
+
+  * Fix network-manager-config-connectivity-ubuntu.postinst
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 29 Nov 2022 14:25:45 -0500
+
+network-manager (1.40.4-1ubuntu1) lunar; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+  * Drop patch that doesn't appear to be needed any more:
+    - ubuntu_revert_systemd.patch (LP: #1914062)
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 20 Sep 2022 13:39:43 -0400
+
 network-manager (1.40.4-1) unstable; urgency=medium
 
   * New upstream version 1.40.4
@@ -370,6 +1303,61 @@ network-manager (1.40.2-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Tue, 18 Oct 2022 12:29:15 +0200
 
+network-manager (1.40.0-1ubuntu2) kinetic; urgency=medium
+
+  * Don't recommend iwd. It's less risky to keep using wpasupplicant
+    for Ubuntu 22.10
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 27 Sep 2022 10:31:16 -0400
+
+network-manager (1.40.0-1ubuntu1) kinetic; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend iwd as preferred alternative to wpasupplicant
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto. See #1070 for why optimize=-lto is also set
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 20 Sep 2022 13:39:43 -0400
+
 network-manager (1.40.0-1) unstable; urgency=medium
 
   * New upstream version 1.40.0
@@ -387,6 +1375,69 @@ network-manager (1.39.90-2) experimental
 
  -- Michael Biebl <biebl@debian.org>  Thu, 25 Aug 2022 12:48:00 +0200
 
+network-manager (1.39.90-1ubuntu3) kinetic; urgency=medium
+
+  * Cherry-pick 2 patches to fix bonding regressions discovered
+    with failing netplan autopkgtests. Thanks Lukas Märdian.
+    (LP: #1987001)
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Thu, 25 Aug 2022 13:26:02 -0400
+
+network-manager (1.39.90-1ubuntu2) kinetic; urgency=medium
+
+  * debian/control:
+    - recommends iwd as a preferred alternative to wpasupplicant since
+      the MIR has been reviewed now
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Thu, 25 Aug 2022 17:09:30 +0200
+
+network-manager (1.39.90-1ubuntu1) kinetic; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto.
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Thu, 18 Aug 2022 08:59:25 -0400
+
 network-manager (1.39.90-1) experimental; urgency=medium
 
   * New upstream version 1.39.90 (1.40 rc1)
@@ -417,6 +1468,53 @@ network-manager (1.38.4-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Sat, 13 Aug 2022 15:51:32 +0200
 
+network-manager (1.38.2-1ubuntu1) kinetic; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto.
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 24 Jun 2022 13:35:27 +0200
+
 network-manager (1.38.2-1) unstable; urgency=medium
 
   * New upstream version 1.38.2
@@ -463,6 +1561,53 @@ network-manager (1.36.4-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 23 Mar 2022 20:39:16 +0100
 
+network-manager (1.36.2-1ubuntu1) jammy; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto.
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Tue, 08 Mar 2022 14:37:15 -0500
+
 network-manager (1.36.2-1) unstable; urgency=medium
 
   * New upstream version 1.36.2
@@ -477,6 +1622,53 @@ network-manager (1.36.0-2) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Sat, 26 Feb 2022 10:57:32 +0100
 
+network-manager (1.36.0-1ubuntu1) jammy; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto.
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Thu, 24 Feb 2022 15:06:34 -0500
+
 network-manager (1.36.0-1) unstable; urgency=medium
 
   * New upstream version 1.36.0
@@ -485,6 +1677,53 @@ network-manager (1.36.0-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Thu, 24 Feb 2022 19:59:26 +0100
 
+network-manager (1.35.92-1ubuntu1) jammy; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto.
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Tue, 22 Feb 2022 17:06:55 -0500
+
 network-manager (1.35.92-1) unstable; urgency=medium
 
   * New upstream version 1.35.92 (1.36 rc3)
@@ -506,6 +1745,80 @@ network-manager (1.35.91-1) unstable; ur
 
  -- Michael Biebl <biebl@debian.org>  Mon, 14 Feb 2022 22:24:06 +0100
 
+network-manager (1.35.91-0ubuntu1) jammy; urgency=medium
+
+  * New upstream release
+  * debian/libnm0.symbols: Add new symbols
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Thu, 10 Feb 2022 14:49:11 -0500
+
+network-manager (1.35.90-0ubuntu1) jammy; urgency=medium
+
+  * New upstream release
+  * Refresh patches
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Tue, 08 Feb 2022 14:12:25 -0500
+
+network-manager (1.34.0-2ubuntu3) jammy; urgency=medium
+
+  * d/tests/control: Have nm.py autopkgtest Depend on wpasupplicant
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Mon, 07 Feb 2022 16:40:52 -0500
+
+network-manager (1.34.0-2ubuntu2) jammy; urgency=medium
+
+  * Revert "Try removing ubuntu_revert_systemd.patch" and refresh the patch
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Thu, 03 Feb 2022 16:11:38 -0500
+
+network-manager (1.34.0-2ubuntu1) jammy; urgency=medium
+
+  * Resynchronize on Debian (LP: #1958710), remaining changes:
+    - debian/control:
+      + Depend on isc-dhcp-client
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules:
+      + Run build tests
+      + Set --enable-lto.
+      + Don't build the network-manager* packages on i386
+        (unneeded and depends on wpasupplicant)
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - d/network-manager.install, d/rules, d/10-dns-resolved.conf:
+      + Use systemd-resolved instead of dnsmasq
+    - d/network-manager.install, d/10-globally-managed-devices.conf:
+      + Explicitly unmanage everything that isn't WiFi or WWAN (mobile data)
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - d/network-manager.install, d/default-wifi-powersave-on.conf:
+      + Install a config file to enable WiFi powersave
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - d/NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+      See gnome-control-center issue 743
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+  * Try removing ubuntu_revert_systemd.patch again
+
+ -- Jeremy Bicha <jeremy.bicha@canonical.com>  Thu, 03 Feb 2022 12:18:58 -0500
+
 network-manager (1.34.0-2) unstable; urgency=medium
 
   * Demote wpasupplicant to Recommends.
@@ -554,6 +1867,112 @@ network-manager (1.30.0-2) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Mon, 12 Apr 2021 21:15:36 +0200
 
+network-manager (1.32.12-0ubuntu2) jammy; urgency=medium
+
+  * debian/tests: drop which usage to fix adt failure in jammy
+
+ -- Dimitri John Ledkov <dimitri.ledkov@canonical.com>  Thu, 11 Nov 2021 12:07:34 +0000
+
+network-manager (1.32.12-0ubuntu1) impish; urgency=medium
+
+  * New upstream version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 27 Sep 2021 17:07:29 +0200
+
+network-manager (1.32.10-0ubuntu1) impish; urgency=medium
+
+  * New upstream version
+  * debian/libnm0.symbols:
+    - updated symbols for the new version
+
+ -- Sebastien Bacher <seb128@debian.org>  Wed, 25 Aug 2021 16:10:58 +0200
+
+network-manager (1.32.2-0ubuntu2) impish; urgency=medium
+
+  * debian/patches/ubuntu_revert_systemd.patch:
+    - restore the workaround for the systemd and lxd issue, it's still
+      needed (lp: #1936312)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Thu, 15 Jul 2021 16:45:08 +0200
+
+network-manager (1.32.2-0ubuntu1) impish; urgency=medium
+
+  * New upstream version
+  * debian/*.py:
+    - update python formatting to be compatible with the checks
+  * debian/patches/ubuntu_revert_systemd.patch:
+    - remove, the issue was fixed in systemd
+  * debian/patches/CVE-2021-20297.patch:
+    - remove, the fix is in the new version
+  * debian/libnm0.symbols
+    - updated for the new version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 05 Jul 2021 20:36:31 +0200
+
+network-manager (1.30.0-1ubuntu4) impish; urgency=medium
+
+  * d/t/nm.py: adapt to changes dnsmasq behavior (LP: #1894619)
+
+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com>  Fri, 02 Jul 2021 11:13:46 +0200
+
+network-manager (1.30.0-1ubuntu3) hirsute; urgency=medium
+
+  * SECURITY UPDATE: crash via setting match.path
+    - debian/patches/CVE-2021-20297.patch: fix match in
+      src/core/nm-core-utils.c.
+    - CVE-2021-20297
+
+ -- Marc Deslauriers <marc.deslauriers@ubuntu.com>  Mon, 12 Apr 2021 06:56:47 -0400
+
+network-manager (1.30.0-1ubuntu2) hirsute; urgency=medium
+
+  * Configure with --enable-lto.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 29 Mar 2021 11:48:39 +0200
+
+network-manager (1.30.0-1ubuntu1) hirsute; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+    - debian/tests/urfkill-integration - don't stop/start network manager
+    - debian/patches/ubuntu_revert_systemd.patch:
+      + temporarly revert an upstream commit that made udev enabled under lxc,
+        the new systemd doesn't work there (lp: #1914062)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Thu, 25 Feb 2021 15:30:59 +0100
+
 network-manager (1.30.0-1) unstable; urgency=medium
 
   * New upstream version 1.30.0
@@ -585,6 +2004,58 @@ network-manager (1.29.90-1) unstable; ur
 
  -- Michael Biebl <biebl@debian.org>  Thu, 11 Feb 2021 20:09:16 +0100
 
+network-manager (1.28.0-2ubuntu2) hirsute; urgency=medium
+
+  * debian/patches/ubuntu_revert_systemd.patch:
+    - temporarly revert an upstream commit that made udev enabled under lxc,
+      the new systemd doesn't work there (lp: #1914062)
+
+  [ Lukas Märdian ]
+  * debian/tests/network_test_base.py:
+    Fix race when reading the MAC address of veth interfaces with new systemd
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Wed, 17 Feb 2021 10:23:07 +0100
+
+network-manager (1.28.0-2ubuntu1) hirsute; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+    - debian/tests/urfkill-integration - don't stop/start network manager
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 11 Jan 2021 18:10:30 +0100
+
 network-manager (1.28.0-2) unstable; urgency=medium
 
   * Demote libpam-systemd to Recommends.
@@ -642,6 +2113,12 @@ network-manager (1.27.90-1) unstable; ur
 
  -- Michael Biebl <biebl@debian.org>  Mon, 05 Oct 2020 23:34:33 +0200
 
+network-manager (1.26.2-1ubuntu1) groovy; urgency=medium
+
+  * Update to the current stable version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 31 Aug 2020 11:09:40 +0200
+
 network-manager (1.26.2-1) unstable; urgency=medium
 
   * New upstream version 1.26.2
@@ -649,6 +2126,46 @@ network-manager (1.26.2-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 19 Aug 2020 10:30:53 +0200
 
+network-manager (1.26.0-1ubuntu1) groovy; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+    - debian/tests/urfkill-integration - don't stop/start network manager
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 27 Jul 2020 17:09:03 +0200
+
 network-manager (1.26.0-1) unstable; urgency=medium
 
   * New upstream version 1.26.0
@@ -679,6 +2196,14 @@ network-manager (1.25.90-1) unstable; ur
 
  -- Michael Biebl <biebl@debian.org>  Sun, 28 Jun 2020 19:29:43 +0200
 
+network-manager (1.24.2-1ubuntu2) groovy; urgency=medium
+
+  * debian/20-connectivity-ubuntu.conf: Add trailing dot to make
+    connectivity-check.ubuntu.com. absolute and reduce NXDOMAIN
+    warning noise, thanks MarchH (lp: #1880258)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 29 Jun 2020 16:20:07 +0200
+
 network-manager (1.24.2-1) unstable; urgency=medium
 
   [ Michael Biebl ]
@@ -690,6 +2215,58 @@ network-manager (1.24.2-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Sun, 21 Jun 2020 13:44:56 +0200
 
+network-manager (1.24.0-1ubuntu2) groovy; urgency=medium
+
+  * debian/rules:
+    - the iptables binary is in /usr/sbin now, use the correct location in
+      the configure. Should fix the hotspot feature not working in GNOME
+      on upgraded systems which haven't been usrmerged.
+      (lp: #1870359)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Wed, 20 May 2020 12:03:07 +0200
+
+network-manager (1.24.0-1ubuntu1) groovy; urgency=medium
+
+  * Resynchronize on Debian, remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - debian/network-manager.maintscript
+      + Remove /etc/dbus-1/system.d/nm-ofono.conf
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+    - debian/tests/urfkill-integration - don't stop/start network manager
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Tue, 19 May 2020 17:07:30 +0200
+
 network-manager (1.24.0-1) unstable; urgency=medium
 
   * New upstream version 1.24.0
@@ -708,6 +2285,26 @@ network-manager (1.23.90-1) unstable; ur
 
  -- Michael Biebl <biebl@debian.org>  Sun, 12 Apr 2020 00:46:53 +0200
 
+network-manager (1.22.10-1ubuntu3) groovy; urgency=medium
+
+  * No-change rebuild to bump Groovy version number.
+
+ -- Dan Streetman <ddstreet@canonical.com>  Thu, 30 Apr 2020 07:47:49 -0400
+
+network-manager (1.22.10-1ubuntu2) focal; urgency=medium
+
+  * d/t/killswitches-no-urfkill
+    - Call udevadm settle before nmcli radio wifi
+      To make sure that change is updated. (LP: #1733321)
+
+ -- Seyeong Kim <seyeong.kim@canonical.com>  Mon, 20 Apr 2020 22:40:44 -0700
+
+network-manager (1.22.10-1ubuntu1) focal; urgency=medium
+
+  * Update to the current stable version, merging from Debian
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 13 Mar 2020 16:27:29 +0100
+
 network-manager (1.22.10-1) unstable; urgency=medium
 
   * New upstream version 1.22.10
@@ -769,6 +2366,22 @@ network-manager (1.22.0-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 18 Dec 2019 19:05:33 +0100
 
+network-manager (1.20.8-1ubuntu2) focal; urgency=medium
+
+  * debian/rules:
+    - Omit building the uninstallable network-manager binary (depends on
+      wpasupplicant) on i386
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 10 Jan 2020 18:26:29 +0100
+
+network-manager (1.20.8-1ubuntu1) focal; urgency=medium
+
+  * New upstream version, merged from Debian
+  * debian/patches/git_wpa_sae.patch:
+    - removed, included in the new version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Tue, 07 Jan 2020 17:00:01 +0100
+
 network-manager (1.20.8-1) unstable; urgency=medium
 
   * New upstream version 1.20.8
@@ -859,6 +2472,107 @@ network-manager (1.18.0-2) experimental;
 
  -- Michael Biebl <biebl@debian.org>  Tue, 28 May 2019 22:27:17 +0200
 
+network-manager (1.18.0-1ubuntu6) eoan; urgency=medium
+
+  [ Till Kamppeter ]
+  * debian/tests/nm.py:
+    + Make activating an AP time out earlier than it otherwise would.
+    + Skip a call that is failing for IPv6 connections.
+
+  [ Iain Lane ]
+  * debian/tests/nm.py: Delete code skipped by the previous change, rather
+    than commenting it out and leaving it inactive in the source.
+
+  [ Sebastien Bacher ]
+  * Updated debian branch from eoan to master
+
+ -- Iain Lane <iain.lane@canonical.com>  Thu, 01 Aug 2019 13:17:35 +0100
+
+network-manager (1.18.0-1ubuntu5) eoan; urgency=medium
+
+  * Updated autopkg test nm.py for API changes in network-manager.
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/tests/control: fix test dependency to list gir1.2-nm-1.0 instead
+    of its old name gir1.2-networkmanager-1.0.
+
+ -- Till Kamppeter <till.kamppeter@canonical.com>  Tue, 25 Jun 2019 13:31:42 +0200
+
+network-manager (1.18.0-1ubuntu4) eoan; urgency=medium
+
+  * debian/tests/nm.py: give test_no_ap more time for wifi devices to start
+    as it may be necessary on ppc64el.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Wed, 29 May 2019 09:31:18 -0400
+
+network-manager (1.18.0-1ubuntu3) eoan; urgency=medium
+
+  * d/p/Read-system-connections-from-run.patch:
+    - remove, upstream addressed it in a different way/for different 
+      reasons in commit ce4dbd7daf.
+  * debian/network-manager-dev.install:
+    - update following the the recent binary changes
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 24 May 2019 11:26:30 +0200
+
+network-manager (1.18.0-1ubuntu2) eoan; urgency=medium
+
+  * debian/control, debian/lib*.install, debian/rules:
+    - remove the deprecated libnm-glib/vpn/util libraries
+  * debian/patches/series:
+    - restore Read-system-connections-from-run.patch which had been
+      dropped by error.
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 24 May 2019 00:07:31 +0200
+
+network-manager (1.18.0-1ubuntu1) eoan; urgency=medium
+
+  * Update to 1.18, merge on Debian, new version includes nwe support for 
+    policy routing rules and for VLAN filtering for Linux bridge.
+  * Remaining Ubuntu changes
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+    - debian/tests/urfkill-integration - don't stop/start network manager
+    - Revert "Add Conflicts to network-manager-dev against deprecated libraries"
+      This reverts commit b4acc5e03e2b821e1cccc69529bb70826c741942.  We're still
+      building libnm-glib for now, so these packages have a use in Ubuntu.
+  * Removed delta, not needed anymore
+    - debian/network-manager.maintscript
+      + Remove /etc/dbus-1/system.d/nm-ofono.conf
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 10 May 2019 15:07:08 +0200
+
 network-manager (1.18.0-1) experimental; urgency=medium
 
   * New upstream version 1.18.0
@@ -902,6 +2616,51 @@ network-manager (1.14.6-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Tue, 26 Feb 2019 19:33:53 +0100
 
+network-manager (1.16.0-0ubuntu2) disco; urgency=medium
+
+  * debian/patches/git_ifupdown_iterator.patch:
+    - ifupdown: fix connection iterator, should fix a segfault in the
+      corresponding plugin (lp: #1815742)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Tue, 02 Apr 2019 17:53:26 +0200
+
+network-manager (1.16.0-0ubuntu1) disco; urgency=medium
+
+  * New upstream version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Tue, 19 Mar 2019 16:23:09 +0100
+
+network-manager (1.15.91-0Ubuntu1) disco; urgency=medium
+
+  * New upstream version
+  * remove patches included in the new version
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Tue, 12 Mar 2019 15:23:26 +0100
+
+network-manager (1.15.2-0ubuntu2) disco; urgency=medium
+
+  * debian/patches/git_ifupdown_segfault.patch:
+    - 'settings/ifupdown: fix ifupdown plugin after merging eni_ifaces and 
+       connections hashes' (lp: #1815742)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 18 Feb 2019 17:06:17 +0100
+
+network-manager (1.15.2-0ubuntu1) disco; urgency=medium
+
+  * Update to the current serie, resynchronize with Debian
+  * debian/libnm0.symbols:
+    - updated for the new version
+  * debian/patches
+    - removed the changes that are included in the new version
+  * debian/patches/git_team_structure.patch:
+    - backport upstream change 'fix team link-watcher struct layout',
+      the tests/build failed on i386
+  * debian/rules:
+    - strip '-Wl,-Bsymbolic-functions' from LDFLAGS otherwise the
+      tests fails on 'cannot register existing type 'NMAgentManagerError''
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 25 Jan 2019 11:31:56 +0100
+
 network-manager (1.14.4-4) unstable; urgency=medium
 
   * Move D-Bus policy files to /usr/share/dbus-1/system.d/
@@ -985,6 +2744,91 @@ network-manager (1.13.90-1) experimental
 
  -- Michael Biebl <biebl@debian.org>  Sat, 08 Sep 2018 18:23:20 +0200
 
+network-manager (1.12.6-0ubuntu4) disco; urgency=medium
+
+  * No-change rebuild for readline soname change.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 14 Jan 2019 20:02:35 +0000
+
+network-manager (1.12.6-0ubuntu3) disco; urgency=medium
+
+  * debian/tests/nm.py: Make assert_iface_down() not check the interface's
+    state. We call nmclient.deactivate_connection() to terminate connections
+    that the testsuite sets up, and according to upstream this is not
+    guaranteed to do anything in particular to the link state. It seems that
+    dnsmasq 2.80 somehow alters the previous assumption that it would be
+    'state DOWN', so the implementation detail we were checking previously no
+    longer holds. The testsuite does still check that the IPs are removed from
+    the interface, which is logically what we want anyway. (LP: #1805857)
+  * debian/control: Fix Vcs-Git
+
+ -- Iain Lane <iain.lane@canonical.com>  Wed, 19 Dec 2018 13:12:58 +0000
+
+network-manager (1.12.6-0ubuntu2) disco; urgency=medium
+
+  [ Robie Basak ]
+  * debian/tests:
+    - Make dep8 nm test directly invokable
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 10 Dec 2018 22:03:01 +0100
+
+network-manager (1.12.6-0ubuntu1) disco; urgency=medium
+
+  * New upstream version
+    - Fix a vulnerability in the internal DHCPv6 client (CVE-2018-15688).
+  * debian/patches/git_mac_change.patch:
+    - backported a regression fix from upstream git
+
+  [ Alfonso Sanchez-Beato ]
+  * Import some WoWLAN patches from the newer stable serie (LP: #1781597)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Mon, 10 Dec 2018 18:50:07 +0100
+
+network-manager (1.12.4-1ubuntu1) cosmic; urgency=medium
+
+  * Merge with Debian (LP: #1795704). Remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet.
+    - debian/network-manager.maintscript
+      + Remove /etc/dbus-1/system.d/nm-ofono.conf
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems.
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+      + Read-system-connections-from-run.patch
+    - debian/tests/urfkill-integration - don't stop/start network manager
+  * Revert "Add Conflicts to network-manager-dev against deprecated libraries"
+    This reverts commit b4acc5e03e2b821e1cccc69529bb70826c741942.  We're still
+    building libnm-glib for now, so these packages have a use in Ubuntu.
+
+ -- Iain Lane <iain.lane@canonical.com>  Wed, 03 Oct 2018 10:03:10 +0100
+
 network-manager (1.12.4-1) unstable; urgency=medium
 
   * New upstream version 1.12.4
@@ -1015,6 +2859,64 @@ network-manager (1.12.2-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 25 Jul 2018 13:35:31 +0200
 
+network-manager (1.12.2-0ubuntu5) cosmic; urgency=medium
+
+  * debian/tests/nm: Add the required `gi.require_version()` calls - thanks to
+    the autopkgtests for noticing this.
+  * debian/tests/control: The nm tests need dnsmasq-base and isc-dhcp-client
+    too.
+
+ -- Iain Lane <iain@orangesquash.org.uk>  Mon, 24 Sep 2018 10:17:30 +0100
+
+network-manager (1.12.2-0ubuntu4) cosmic; urgency=medium
+
+  Cherry-pick fixes from debian:
+  * Fix compile error due to NM_AVAILABLE_IN_1_12_2 macro in n-m-applet
+  * Apply patch from upstream to fix FTBFS with GLib 2.57
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 10 Sep 2018 11:36:35 +0200
+
+network-manager (1.12.2-0ubuntu3) cosmic; urgency=medium
+
+  * debian/rules:
+    - use --with-libnm-glib, the default reversed since that's a legacy
+      library but we still need it for unity-control-center
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 24 Aug 2018 11:00:09 +0200
+
+network-manager (1.12.2-0ubuntu2) cosmic; urgency=medium
+
+  * debian/patches/git-newglib-test.patch:
+    - backport upstream commit to fix the tests with the new glib 
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 24 Aug 2018 10:44:12 +0200
+
+network-manager (1.12.2-0ubuntu1) cosmic; urgency=medium
+
+  * New upstream version
+  * d/p/libnm-register-empty-NMClient-and-NetworkManager-when-loa.patch,
+    d/p/e91f1a7d2a6b8400b6b331d5b72287dcb5164a39.patch,
+    d/p/git_thunderbolt_connect.patch:
+    - removed, those changes are in the new version
+  * Backport Debian changes
+  * Update symbols file for libnm0
+  * Enable iwd support
+  * Drop version requirements when oldstable ships a newer version
+  * Drop dh_strip override, the dbgsym migration is done
+  * Rebase patches
+  * Make sure the example server.conf is actually installed
+  * Update install path for plugins, it now includes a version number
+  * Drop libnl3 build dependency.
+    Upstream has copied the code directly from libnl3 for the few functions it
+    needs with a few small modifications.
+  * Drop libiw build dependency.
+    Hasn't been needed for a long time and was simply a left over from older
+    releases.
+  * Bump Standards-Version to 4.1.5
+  * Fix compile error due to NM_AVAILABLE_IN_1_12_2 macro (Closes: #905372)
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 24 Aug 2018 09:27:39 +0200
+
 network-manager (1.12.0-5) unstable; urgency=medium
 
   * manager: accept non-null device for VPN activations (Closes: #903109)
@@ -1098,6 +3000,75 @@ network-manager (1.11.3-1) experimental;
 
  -- Michael Biebl <biebl@debian.org>  Mon, 23 Apr 2018 23:35:35 +0200
 
+network-manager (1.10.8-1ubuntu4) cosmic; urgency=medium
+
+  * debian/10-globally-managed-devices.conf: adjust exception for wwan to
+    specify cdma and gsm, since those are the actual types handled by NM/MM.
+    (LP: #1780606)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Tue, 10 Jul 2018 08:17:11 -0400
+
+network-manager (1.10.8-1ubuntu3) cosmic; urgency=medium
+
+  * Revert the changes to remove the nmclient bindings, those are needed
+    to build nm-applet until the legacy binaries can be removed, which
+    requires unity-control-center to be updated to use the new library.
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Wed, 04 Jul 2018 15:30:19 +0200
+
+network-manager (1.10.8-1ubuntu2) cosmic; urgency=medium
+
+  * debian/patches/git_thunderbolt_connect.patch:
+    - enable host to host connection through thunderbolt
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Fri, 25 May 2018 16:54:48 +0200
+
+network-manager (1.10.8-1ubuntu1) cosmic; urgency=medium
+
+  * Merge with Debian (LP: #1758331). Remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet. (LP: #1676547)
+    - debian/network-manager.maintscript
+      + Remove /etc/dbus-1/system.d/nm-ofono.conf
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems. (LP: #1681513)
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch
+      + Read-system-connections-from-run.patch
+      + e91f1a7d2a6b8400b6b331d5b72287dcb5164a39.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+    - debian/tests/urfkill-integration - don't stop/start network manager
+  * Keep libnm-glib/libnm-util a bit longer since unity-control-center
+    still needs them. See bug 1744619
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Fri, 11 May 2018 19:52:40 -0400
+
 network-manager (1.10.8-1) unstable; urgency=medium
 
   * New upstream version 1.10.8
@@ -1113,6 +3084,52 @@ network-manager (1.10.6-3) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Wed, 18 Apr 2018 19:40:01 +0200
 
+network-manager (1.10.6-2ubuntu1) bionic; urgency=medium
+
+  * Merge with Debian (LP: #1758331). Remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet. (LP: #1676547)
+    - debian/network-manager.maintscript
+      + Remove /etc/dbus-1/system.d/nm-ofono.conf
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems. (LP: #1681513)
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch
+      + Read-system-connections-from-run.patch
+      + e91f1a7d2a6b8400b6b331d5b72287dcb5164a39.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch (but disabled)
+    - debian/tests/urfkill-integration - don't stop/start network manager
+  * Dropped patches applied in new release:
+    - settings-preserve-agent-owned-secrets-on-connection-updat.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Mon, 26 Mar 2018 09:21:12 -0400
+
 network-manager (1.10.6-2) unstable; urgency=medium
 
   * Update Vcs-* to point to https://salsa.debian.org
@@ -1126,6 +3143,82 @@ network-manager (1.10.6-1) unstable; urg
 
  -- Michael Biebl <biebl@debian.org>  Tue, 13 Mar 2018 01:47:52 +0100
 
+network-manager (1.10.4-1ubuntu3) bionic; urgency=medium
+
+  * Cherry-pick a partial patch from 1.11 branch, to stop agressively
+    setting route_only flag on nameservers in the systemd-resolved dns
+    plugin. LP: #1751797
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Thu, 15 Mar 2018 15:24:01 +0000
+
+network-manager (1.10.4-1ubuntu2) bionic; urgency=medium
+
+  [ Bryan Quigley ]
+  * debian/tests/urfkill-integration - don't stop/start network manager
+
+  [ Jeremy Bicha ]
+  * Cherry-pick patch from 1.10 branch to fix double prompt for wifi password
+    on Kubuntu (LP: #1572244)
+
+ -- Bryan Quigley <bryan.quigley@canonical.com>  Fri, 23 Feb 2018 13:52:48 -0500
+
+network-manager (1.10.4-1ubuntu1) bionic; urgency=medium
+
+  * Merge with Debian (LP: #1734586). Remaining changes:
+    - Use systemd-resolved instead of dnsmasq
+    - debian/control:
+      + Depend on isc-dhcp-client instead of recommends
+      + Recommend network-manager-pptp
+      + Suggest avahi-autoipd for IPv4LL support
+    - debian/rules, debian/network-manager.postinst:
+      + Don't restart NetworkManager on upgrade but recommend restarting
+        the computer
+    - debian/rules, debian/network-manager.postinst:
+      + Don't install sysvinit scripts or migrate from sysvinit
+    - debian/network-manager.postinst:
+      + Don't add the netdev group.
+      + drop in an empty override file for NetworkManager to manage all
+        devices for upgrade from any version, as long as there is no
+        netplan configuration yet. (LP: #1676547)
+    - debian/network-manager.maintscript
+      + Remove /etc/dbus-1/system.d/nm-ofono.conf
+    - debian/default-wifi-powersave-on.conf, debian/rules:
+      + Install a config file to enable WiFi powersave
+    - Enable build tests
+    - Add autopkgtests
+    - debian/source_network-manager.py, debian/network-manager.install,
+      debian/network-manager.links: Add apport hook
+    - Add network-manager-config-connectivity-ubuntu package
+    - NetworkManager.conf: disable MAC randomization feature. There is no
+      easy way for desktop users to disable this feature yet. And there are
+      reports that it doesn't work well with some systems. (LP: #1681513)
+    - Update Vcs links to point to Ubuntu branch
+    - Add patches. See patch descriptions for more details:
+      + Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+      + Update-dnsmasq-parameters.patch
+      + Disable-general-with-expect.patch
+      + libnm-Check-self-still-NMManager-or-not.patch
+      + dns-manager-don-t-merge-split-DNS-search-domains.patch
+      + Read-system-connections-from-run.patch
+  * Disable dns-manager-don-t-merge-split-DNS-search-domains.patch:
+    This patch needs to be updated for the new release but so far, no
+    one that understands the issue and patch have worked to update it.
+    After waiting for several weeks, we thought it was more important
+    to get this major version update into bionic now.
+  * Dropped patches applied in new release:
+    - connectivity-allow-override.patch
+    - nm1.10-connectivity-check-api.patch
+    - fix-resolved-detection.patch
+  * Other dropped changes:
+    - debian/control, debian/rules:
+      + Disable team support since it's in universe (LP: #1392012)
+    - Obsolete Ubuntu Phone related patches:
+      + Ignore-p2p0-wifi-devices-from-android.patch
+      + Ignore-rmnet_usbX-devices.patch'
+      + Track-killswitch-change-signals-from-urfkill.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Fri, 09 Feb 2018 12:21:37 -0500
+
 network-manager (1.10.4-1) unstable; urgency=medium
 
   [ Laurent Bigonville ]
@@ -3583,7 +5676,7 @@ network-manager (0.4.1+cvs20050616-1) br
   * New upstream. Fix descriptions.
 
  -- Thom May <thom@ubuntu.com>  Thu, 16 Jun 2005 14:47:30 +0100
-   
+
 network-manager (0.4.1+cvs20050614-1) unstable; urgency=low
 
   * New upstream release. Move to 0.4 branch; use dhcdbd.
@@ -3641,4 +5734,3 @@ network-manager (0.2+cvs20040928-1) unst
   * Initial Release.
 
  -- Thom May <thom@debian.org>  Sun,  3 Oct 2004 11:54:56 +0100
-
diff -pruN 1.52.0-1/debian/control 1.52.0-1ubuntu1/debian/control
--- 1.52.0-1/debian/control	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/control	2025-03-03 17:49:02.000000000 +0000
@@ -1,7 +1,8 @@
 Source: network-manager
 Section: net
 Priority: optional
-Maintainer: Utopia Maintenance Team <pkg-utopia-maintainers@lists.alioth.debian.org>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Utopia Maintenance Team <pkg-utopia-maintainers@lists.alioth.debian.org>
 Uploaders: Michael Biebl <biebl@debian.org>
 Build-Depends: debhelper-compat (= 13),
                debhelper (>= 13.11.6),
@@ -43,10 +44,15 @@ Build-Depends: debhelper-compat (= 13),
                python3-dbus <!nocheck>,
                python3-pexpect <!nocheck>,
                iproute2 <!nocheck>,
+               libyaml-dev [!i386],
+               libnetplan-dev (>= 1.0~) [!i386],
+               netplan.io (>= 1.0~) [!i386] <!nocheck>,
 Standards-Version: 4.7.0
 Rules-Requires-Root: no
-Vcs-Git: https://salsa.debian.org/utopia-team/network-manager.git
-Vcs-Browser: https://salsa.debian.org/utopia-team/network-manager
+XS-Debian-Vcs-Git: https://salsa.debian.org/utopia-team/network-manager.git
+XS-Debian-Vcs-Browser: https://salsa.debian.org/utopia-team/network-manager
+Vcs-Git: https://git.launchpad.net/network-manager
+Vcs-Browser: https://git.launchpad.net/network-manager
 Homepage: https://networkmanager.dev/
 
 Package: network-manager
@@ -54,18 +60,21 @@ Architecture: linux-any
 Pre-Depends: ${misc:Pre-Depends}
 Depends: ${shlibs:Depends},
          ${misc:Depends},
+         netplan.io (>= 1.0~) [!i386],
          libnm0 (= ${binary:Version}),
          default-dbus-system-bus | dbus-system-bus,
          adduser,
 Recommends: ppp,
             dnsmasq-base,
             modemmanager,
+            network-manager-pptp,
             wireless-regdb,
             wpasupplicant,
             libpam-systemd,
             polkitd,
             udev,
-Suggests: libteam-utils,
+Suggests: avahi-autoipd,
+          libteam-utils,
           iptables,
 Breaks: ${misc:Breaks}
 Description: network management framework (daemon and userspace tools)
@@ -79,6 +88,8 @@ Description: network management framewor
  interact with NetworkManager.
  .
  Optional dependencies:
+  * avahi-autoipd: Used for IPv4LL, a protocol for automatic Link-Local IP
+    address configuration.
   * ppp: Required for establishing dial-up connections (e.g. via GSM).
   * dnsmasq-base/iptables: Required for creating Ad-hoc connections and
     connection sharing.
@@ -167,3 +178,21 @@ Description: NetworkManager configuratio
  No user data is transmitted in the connectivity checks, but merely contacting
  the Debian connectivity check servers reveals that the user is running a
  Debian(-based) operating system with NetworkManager.
+
+Package: network-manager-config-connectivity-ubuntu
+Architecture: all
+Multi-Arch: foreign
+Depends: ${misc:Depends},
+         network-manager (>= ${source:Version})
+Description: NetworkManager configuration to enable connectivity checking
+ This package contains a configuration file which enables NetworkManager's
+ connectivity checking functionality.
+ .
+ NetworkManager will try to connect to an Ubuntu server to determine the
+ connection status.
+ .
+ This is particularly useful for captive portal detection.
+ .
+ No user data is transmitted in the connectivity checks, but merely contacting
+ the Ubuntu connectivity check servers reveals that the user is running an
+ Ubuntu(-based) operating system with NetworkManager.
diff -pruN 1.52.0-1/debian/default-wifi-powersave-on.conf 1.52.0-1ubuntu1/debian/default-wifi-powersave-on.conf
--- 1.52.0-1/debian/default-wifi-powersave-on.conf	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/default-wifi-powersave-on.conf	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,2 @@
+[connection]
+wifi.powersave = 3
diff -pruN 1.52.0-1/debian/gbp.conf 1.52.0-1ubuntu1/debian/gbp.conf
--- 1.52.0-1/debian/gbp.conf	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/gbp.conf	2025-03-03 17:49:02.000000000 +0000
@@ -1,5 +1,6 @@
 [DEFAULT]
 pristine-tar = True
 patch-numbers = False
-debian-branch = debian/master
+debian-branch = ubuntu/master
+debian-tag = ubuntu/%(version)s
 upstream-branch = upstream/latest
diff -pruN 1.52.0-1/debian/network-manager-config-connectivity-ubuntu.install 1.52.0-1ubuntu1/debian/network-manager-config-connectivity-ubuntu.install
--- 1.52.0-1/debian/network-manager-config-connectivity-ubuntu.install	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/network-manager-config-connectivity-ubuntu.install	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1 @@
+debian/20-connectivity-ubuntu.conf usr/lib/NetworkManager/conf.d/
diff -pruN 1.52.0-1/debian/network-manager-config-connectivity-ubuntu.postinst 1.52.0-1ubuntu1/debian/network-manager-config-connectivity-ubuntu.postinst
--- 1.52.0-1/debian/network-manager-config-connectivity-ubuntu.postinst	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/network-manager-config-connectivity-ubuntu.postinst	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = configure ]; then
+    nmcli general reload 2>/dev/null || true
+fi
+
+#DEBHELPER#
diff -pruN 1.52.0-1/debian/network-manager.install 1.52.0-1ubuntu1/debian/network-manager.install
--- 1.52.0-1/debian/network-manager.install	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/network-manager.install	2025-03-03 17:49:02.000000000 +0000
@@ -24,3 +24,6 @@ etc/NetworkManager/
 var/lib/NetworkManager/
 debian/NetworkManager.conf etc/NetworkManager/
 debian/org.freedesktop.NetworkManager.rules usr/share/polkit-1/rules.d/
+debian/10-*.conf usr/lib/NetworkManager/conf.d/
+debian/default-wifi-powersave-on.conf etc/NetworkManager/conf.d
+debian/source_network-manager.py /usr/share/apport/package-hooks/
diff -pruN 1.52.0-1/debian/network-manager.links 1.52.0-1ubuntu1/debian/network-manager.links
--- 1.52.0-1/debian/network-manager.links	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/network-manager.links	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1 @@
+/usr/share/apport/package-hooks/source_network-manager.py /usr/share/apport/package-hooks/source_network-manager-applet.py
diff -pruN 1.52.0-1/debian/network-manager.postinst 1.52.0-1ubuntu1/debian/network-manager.postinst
--- 1.52.0-1/debian/network-manager.postinst	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/network-manager.postinst	2025-03-03 17:49:02.000000000 +0000
@@ -20,9 +20,11 @@ set -e
 
 case "$1" in
     configure)
-        # Create netdev group. Members of group netdev get access to the PolicyKit action
-        # org.freedesktop.NetworkManager.settings.modify.system without prior authentication
-        addgroup --quiet --system netdev
+        update-rc.d -f NetworkManager remove >/dev/null
+
+        if [ -x "/etc/init.d/dbus" ]; then
+            invoke-rc.d dbus force-reload || true
+        fi
 
         # This directory can contain sensitive data and should not be world-readable
         chmod 0700 /var/lib/NetworkManager
@@ -57,3 +59,41 @@ esac
 
 #DEBHELPER#
 
+# Run "Netplan Everywhere" migration after debhelper (re-)started
+# NetworkManager.service for us. On every package upgrade.
+DIR="/etc/NetworkManager/system-connections"
+if [ "$1" = "configure" ] && [ -d "$DIR" ]; then
+    mkdir -p /run/netplan/nm-migrate
+    for CON in /etc/NetworkManager/system-connections/*; do
+        TYPE=$(file -bi "$CON" | cut -s -d ";" -f 1)
+        [ "$TYPE" = "text/plain" ] || continue # skip non-keyfiles
+        UUID=$(grep "^uuid=" "$CON" | cut -c 6-)
+        if [ -n "$UUID" ]
+        then
+            # Wait for NetworkManager startup to complete,
+            # so we can safely use nmcli. Wait in every interation to handle
+            # a crashed NetworkManager in the previous migraiton step.
+            if ! nm-online -qs; then
+                echo "SKIP: NetworkManager is not ready ..." 1>&2
+                continue
+            fi
+            BACKUP="/run/netplan/nm-migrate/"$(basename "$CON")
+            ORIG_NAME=$(nmcli --get-values connection.id con show "$UUID") || \
+                { echo "SKIP: $(basename "$CON") ($UUID) unknown to NetworkManager." 1>&2 && \
+                  continue; }
+            cp "$CON" "$BACKUP"
+            echo "Migrating $ORIG_NAME ($UUID) to /etc/netplan" 1>&2
+            # Touch the connection's ID (con-name) to trigger its migration.
+            # The Netplan integration will translate the original NM keyfile from
+            # /etc/NetworkManager/system-connections/* to a YAML file located in
+            # /etc/netplan/90-NM-*.yaml and re-generate a corresponding keyfile in
+            # /run/NetworkManager/system-connections/netplan-NM-*.nmconnection
+            nmcli con mod "$UUID" con-name "$ORIG_NAME" || \
+                (echo "FAILED. Restoring backup ..." 1>&2 && mv "$BACKUP" "$CON" && \
+                 rm -f "/etc/netplan/90-NM-$UUID"*.yaml)
+            rm -f "$BACKUP" # clear backup (if it still exists)
+       fi
+    done
+    rm -rf /run/netplan/nm-migrate # cleanup after ourselves
+    (nm-online -qs && nmcli con reload) || echo "WARNING: NetworkManager could not reload connections ..." 1>&2
+fi
diff -pruN 1.52.0-1/debian/network-manager.preinst 1.52.0-1ubuntu1/debian/network-manager.preinst
--- 1.52.0-1/debian/network-manager.preinst	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/network-manager.preinst	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+set -e
+
+#DEBHELPER#
+
+DIR="/etc/NetworkManager/system-connections"
+BACKUP_DIR="/var/lib/NetworkManager/backups"
+CNT=$(ls -1 "$DIR" | wc -l)
+if ([ "$1" = "upgrade" ] || [ "$1" = "install" ]) && [ -d "$DIR" ] && [ "$CNT" -ge 1 ]; then
+    # create backup directory if it does not yet exist
+    mkdir -p "$BACKUP_DIR" || true
+    BAK="$BACKUP_DIR/system-connections_$2"
+    if [ -d "$BAK" ]; then
+	rm -r "$BAK"
+    fi
+    # copy current system-connections to the backup directory
+    cp -r "$DIR" "$BAK"
+fi
diff -pruN 1.52.0-1/debian/patches/Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch 1.52.0-1ubuntu1/debian/patches/Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
--- 1.52.0-1/debian/patches/Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/patches/Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,35 @@
+From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Date: Thu, 12 May 2016 22:25:32 +0800
+Subject: Provide access to some of NM's interfaces to whoopsie.
+
+Whoopsie is the crash database reporting daemon. It needs access to some of
+the information NM keeps about devices to avoid sending data over the network
+when connected to 3G or other systems that are potentially billable.
+---
+ src/core/org.freedesktop.NetworkManager.conf | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/src/core/org.freedesktop.NetworkManager.conf b/src/core/org.freedesktop.NetworkManager.conf
+index 5c2af2e..f56c7fb 100644
+--- a/src/core/org.freedesktop.NetworkManager.conf
++++ b/src/core/org.freedesktop.NetworkManager.conf
+@@ -37,6 +37,19 @@
+         <allow own="org.freedesktop.NetworkManager.dnsmasq"/>
+         <allow send_destination="org.freedesktop.NetworkManager.dnsmasq"/>
+     </policy>
++    <policy user="whoopsie">
++            <allow send_destination="org.freedesktop.NetworkManager"/>
++            <allow send_destination="org.freedesktop.NetworkManager"
++                   send_interface="org.freedesktop.DBus.Introspectable"/>
++            <allow send_destination="org.freedesktop.NetworkManager"
++                   send_interface="org.freedesktop.DBus.Properties"/>
++            <allow send_destination="org.freedesktop.NetworkManager"
++                   send_interface="org.freedesktop.NetworkManager"/>
++            <allow send_destination="org.freedesktop.NetworkManager"
++                   send_interface="org.freedesktop.NetworkManager.Connection.Active"/>
++            <allow send_destination="org.freedesktop.NetworkManager"
++                   send_interface="org.freedesktop.NetworkManager.Device"/>
++    </policy>
+     <policy context="default">
+         <deny own="org.freedesktop.NetworkManager"/>
+ 
diff -pruN 1.52.0-1/debian/patches/Update-dnsmasq-parameters.patch 1.52.0-1ubuntu1/debian/patches/Update-dnsmasq-parameters.patch
--- 1.52.0-1/debian/patches/Update-dnsmasq-parameters.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/patches/Update-dnsmasq-parameters.patch	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,55 @@
+From: =?utf-8?q?St=C3=A9phane_Graber?= <stephane.graber@canonical.com>
+Date: Thu, 12 May 2016 22:44:06 +0800
+Subject: Update dnsmasq parameters
+
+Disable caching since it's a potential security issue (local dns cache poisoning).
+
+See also: https://blueprints.launchpad.net/ubuntu/+spec/foundations-p-dns-resolving
+---
+ src/core/dns/nm-dns-dnsmasq.c | 4 ++--
+ src/core/dns/nm-dns-manager.c | 6 +++---
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/src/core/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c
+index 8e3c10c..48a0fe5 100644
+--- a/src/core/dns/nm-dns-dnsmasq.c
++++ b/src/core/dns/nm-dns-dnsmasq.c
+@@ -523,8 +523,8 @@ _gl_pid_spawn_next_step(void)
+     argv[argv_idx++] = "--no-hosts"; /* don't use /etc/hosts to resolve */
+     argv[argv_idx++] = "--bind-interfaces";
+     argv[argv_idx++] = "--pid-file=" PIDFILE;
+-    argv[argv_idx++] = "--listen-address=127.0.0.1"; /* Should work for both 4 and 6 */
+-    argv[argv_idx++] = "--cache-size=400";
++    argv[argv_idx++] = "--listen-address=127.0.1.1"; /* Should work for both 4 and 6 */
++    argv[argv_idx++] = "--cache-size=0";
+     argv[argv_idx++] = "--clear-on-reload";     /* clear cache when dns server changes */
+     argv[argv_idx++] = "--conf-file=/dev/null"; /* avoid loading /etc/dnsmasq.conf */
+     argv[argv_idx++] = "--enable-dbus=" DNSMASQ_DBUS_SERVICE;
+diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c
+index d47590d..07b6225 100644
+--- a/src/core/dns/nm-dns-manager.c
++++ b/src/core/dns/nm-dns-manager.c
+@@ -1859,12 +1859,12 @@ plugin_skip:;
+                                NM_CAST_STRV_CC(nameservers),
+                                NM_CAST_STRV_CC(options));
+ 
+-    /* If caching was successful, we only send 127.0.0.1 to /etc/resolv.conf
++    /* If caching was successful, we only send 127.0.1.1 to /etc/resolv.conf
+      * to ensure that the glibc resolver doesn't try to round-robin nameservers,
+      * but only uses the local caching nameserver.
+      */
+     if (caching) {
+-        const char *lladdr = "127.0.0.1";
++        const char *lladdr = "127.0.1.1";
+         gboolean    need_edns0;
+         gboolean    need_trust;
+ 
+@@ -2291,7 +2291,7 @@ nm_dns_manager_stop(NMDnsManager *self)
+     _LOGT("stopping...");
+ 
+     /* If we're quitting, leave a valid resolv.conf in place, not one
+-     * pointing to 127.0.0.1 if dnsmasq was active.  But if we haven't
++     * pointing to 127.0.1.1 if dnsmasq was active.  But if we haven't
+      * done any DNS updates yet, there's no reason to touch resolv.conf
+      * on shutdown.
+      */
diff -pruN 1.52.0-1/debian/patches/netplan/0001-netplan-Adopt-buildsystems-for-Netplan-integration.patch 1.52.0-1ubuntu1/debian/patches/netplan/0001-netplan-Adopt-buildsystems-for-Netplan-integration.patch
--- 1.52.0-1/debian/patches/netplan/0001-netplan-Adopt-buildsystems-for-Netplan-integration.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/patches/netplan/0001-netplan-Adopt-buildsystems-for-Netplan-integration.patch	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,82 @@
+From: =?utf-8?q?Lukas_M=C3=A4rdian?= <slyon@ubuntu.com>
+Date: Tue, 9 May 2023 17:09:48 +0200
+Subject: [PATCH 1/2] netplan: Adopt buildsystems for Netplan integration
+
+Meson will define a "WITH_NETPLAN" variable with the
+values 1 or 0 accordingly, using the config.h header.
+---
+ config.h.meson       |  2 ++
+ meson.build          | 10 ++++++++++
+ meson_options.txt    |  1 +
+ src/core/meson.build |  1 +
+ 4 files changed, 14 insertions(+)
+
+diff --git a/config.h.meson b/config.h.meson
+index e59160d..9a44e81 100644
+--- a/config.h.meson
++++ b/config.h.meson
+@@ -277,3 +277,5 @@
+ /* Define to 1 if you have history support from -lreadline. */
+ #mesondefine HAVE_READLINE_HISTORY
+ 
++/* Define to 1 to enable integration with Netplan */
++#mesondefine WITH_NETPLAN
+diff --git a/meson.build b/meson.build
+index 52bd072..c1f12da 100644
+--- a/meson.build
++++ b/meson.build
+@@ -287,6 +287,8 @@ config_h.set10('HAVE_LIBSYSTEMD', libsystemd_dep.found())
+ 
+ systemd_dep = dependency('systemd', required: false)
+ 
++libnetplan_dep = dependency('netplan', version: '>= 0.106', required: false)
++
+ gio_unix_dep = dependency('gio-unix-2.0', version: '>= 2.42')
+ 
+ glib_dep = declare_dependency(
+@@ -678,6 +680,13 @@ if enable_ovs
+ endif
+ config_h.set10('WITH_OPENVSWITCH', enable_ovs)
+ 
++# Netplan integration
++enable_netplan = get_option('netplan')
++if enable_netplan
++  assert(libnetplan_dep.found(), 'libnetplan is needed for Netplan integration.')
++endif
++config_h.set10('WITH_NETPLAN', enable_netplan)
++
+ # DNS resolv.conf managers
+ config_dns_rc_manager_default = get_option('config_dns_rc_manager_default')
+ config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_RC_MANAGER', config_dns_rc_manager_default)
+@@ -1135,6 +1144,7 @@ output += '  ofono: ' + enable_ofono.to_string() + '\n'
+ output += '  concheck: ' + enable_concheck.to_string() + '\n'
+ output += '  libteamdctl: ' + enable_teamdctl.to_string() + '\n'
+ output += '  ovs: ' + enable_ovs.to_string() + '\n'
++output += '  netplan: ' + enable_netplan.to_string() + '\n'
+ output += '  nmcli: ' + enable_nmcli.to_string() + '\n'
+ output += '  nmtui: ' + enable_nmtui.to_string() + '\n'
+ output += '  nm-cloud-setup: ' + enable_nm_cloud_setup.to_string() + '\n'
+diff --git a/meson_options.txt b/meson_options.txt
+index 4bc11aa..40470c5 100644
+--- a/meson_options.txt
++++ b/meson_options.txt
+@@ -39,6 +39,7 @@ option('ofono', type: 'boolean', value: false, description: 'Enable oFono suppor
+ option('concheck', type: 'boolean', value: true, description: 'enable connectivity checking support')
+ option('teamdctl', type: 'boolean', value: false, description: 'enable Teamd control support')
+ option('ovs', type: 'boolean', value: true, description: 'enable Open vSwitch support')
++option('netplan', type: 'boolean', value: true, description: 'Enable Netplan integration')
+ option('nmcli', type: 'boolean', value: true, description: 'Build nmcli')
+ option('nmtui', type: 'boolean', value: true, description: 'Build nmtui')
+ option('nm_cloud_setup', type: 'boolean', value: true, description: 'Build nm-cloud-setup, a tool for automatically configuring networking in cloud')
+diff --git a/src/core/meson.build b/src/core/meson.build
+index 6cf891e..7bb096b 100644
+--- a/src/core/meson.build
++++ b/src/core/meson.build
+@@ -71,6 +71,7 @@ nm_deps = [
+   libndp_dep,
+   libudev_dep,
+   logind_dep,
++  libnetplan_dep,
+ ]
+ 
+ if enable_concheck
diff -pruN 1.52.0-1/debian/patches/netplan/0002-netplan-make-use-of-libnetplan-for-YAML-backend.patch 1.52.0-1ubuntu1/debian/patches/netplan/0002-netplan-make-use-of-libnetplan-for-YAML-backend.patch
--- 1.52.0-1/debian/patches/netplan/0002-netplan-make-use-of-libnetplan-for-YAML-backend.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/patches/netplan/0002-netplan-make-use-of-libnetplan-for-YAML-backend.patch	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,522 @@
+From: =?utf-8?q?Lukas_M=C3=A4rdian?= <lukas.maerdian@canonical.com>
+Date: Tue, 2 Feb 2021 15:52:05 +0100
+Subject: [PATCH 2/2] netplan: make use of libnetplan for YAML backend
+
+Origin: https://github.com/slyon/NetworkManager/tree/netplan-nm-1.42
+Forwarded: no, https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/556
+Last-Update: 2023-05-11
+
+This patch modifies NetworkManager's nms-keyfile-plugin in a way to
+write YAML connections (according to the netplan spec) to
+/etc/netplan/*.yaml instead of NM's native keyfile connection profiles
+in /etc/NetworkManager/system-connections/*.nmconnection.
+
+Whenever a connection profile is to be written (add/modify) the keyfile,
+generated internally by NM, is passed into libnetplan's
+"netplan_parser_load_keyfile()" API, validated via
+"netplan_state_import_parser_results()" and converted to a netplan YAML
+config by calling libnetplan's "netplan_netdef_write_yaml()" API. The
+internal keyfile is thrown away afterwards.
+
+Whenever a connection profile is to be deleted the netplan-/netdef-id is
+extracted from the ephemeral keyfile in /run/NetworkManager/system-connections
+via "netplan_get_id_from_nm_filepath()" and the corresponding YAML is
+updated/deleted by calling "netplan_delete_connection()".
+
+Each time the YAML data was modified, NetworkManager calls
+"netplan generate" to produce new ephemeral keyfile connections in
+/run/NetworkManager/system-connections for NM to read-back. This way the
+netplan generator can be used as intended (no need for duplicated
+keyfile export functionality) and the nms-keyfile-writer can be re-used
+without any patching needed.
+
+V2:
++ ported to NetworkManager 1.36.6 (Ubuntu Jammy LTS/Core 22.04)
++ test-keyfile-settings.c: clear netplan YAML config from previous runs
++ nms-keyfile-writer.c: avoid double-free of `path` on exit, caused by gs_free
+
+V3:
++ ported to NM 1.40.6 (Ubuntu Lunar), using new libnetplan API (v0.106)
++ ignore .nm-generated connections (LP: #1998207)
+
+V4:
++ encapsulated all Netplan code in "#if WITH_NETPLAN" as provided by the
+  buildsystems via config.h (see previous commit)
++ nms-keyfile-writer.c: increase buffer size to account for ".nmconnection"
+  suffix in netplan_netdef_get_output_filename()
+
+Co-authored-by: Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
+Co-authored-by: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
+---
+ .../settings/plugins/keyfile/nms-keyfile-plugin.c  |  34 ++++
+ .../settings/plugins/keyfile/nms-keyfile-utils.c   |  18 +++
+ .../settings/plugins/keyfile/nms-keyfile-utils.h   |   4 +
+ .../settings/plugins/keyfile/nms-keyfile-writer.c  | 173 +++++++++++++++++++++
+ .../plugins/keyfile/tests/test-keyfile-settings.c  |  62 +++++++-
+ 5 files changed, 287 insertions(+), 4 deletions(-)
+
+diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c
+index 681eef8..a1cc852 100644
+--- a/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c
++++ b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c
+@@ -12,6 +12,9 @@
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
++#if WITH_NETPLAN
++#include <netplan/util.h>
++#endif
+ 
+ #include "libnm-std-aux/c-list-util.h"
+ #include "libnm-glib-aux/nm-c-list.h"
+@@ -309,6 +312,12 @@ _load_file(NMSKeyfilePlugin     *self,
+     gs_free char                 *full_filename    = NULL;
+     struct stat                   st;
+ 
++    #if WITH_NETPLAN
++    // Handle all netplan generated connections via STORAGE_TYPE_ETC, as they live in /etc/netplan
++    if (g_str_has_prefix(filename, "netplan-"))
++        storage_type = NMS_KEYFILE_STORAGE_TYPE_ETC;
++    #endif
++
+     if (_ignore_filename(storage_type, filename)) {
+         gs_free char *nmmeta                    = NULL;
+         gs_free char *loaded_path               = NULL;
+@@ -584,6 +593,9 @@ reload_connections(NMSettingsPlugin                      *plugin,
+         NM_SETT_UTIL_STORAGES_INIT(storages_new, nms_keyfile_storage_destroy);
+     int i;
+ 
++    #if WITH_NETPLAN
++    generate_netplan(NULL);
++    #endif
+     _load_dir(self, NMS_KEYFILE_STORAGE_TYPE_RUN, priv->dirname_run, &storages_new);
+     if (priv->dirname_etc)
+         _load_dir(self, NMS_KEYFILE_STORAGE_TYPE_ETC, priv->dirname_etc, &storages_new);
+@@ -1045,6 +1057,15 @@ delete_connection(NMSettingsPlugin *plugin, NMSettingsStorage *storage_x, GError
+     previous_filename = nms_keyfile_storage_get_filename(storage);
+     uuid              = nms_keyfile_storage_get_uuid(storage);
+ 
++    #if WITH_NETPLAN
++    nm_auto_unref_keyfile GKeyFile *key_file = NULL;
++    key_file = g_key_file_new ();
++    if (!g_key_file_load_from_file (key_file, previous_filename, G_KEY_FILE_NONE, error))
++        return FALSE;
++    g_autofree gchar* ssid = NULL;
++    ssid = g_key_file_get_string(key_file, "wifi", "ssid", NULL);
++    #endif
++
+     if (!NM_IN_SET(storage->storage_type,
+                    NMS_KEYFILE_STORAGE_TYPE_ETC,
+                    NMS_KEYFILE_STORAGE_TYPE_RUN)) {
+@@ -1070,6 +1091,19 @@ delete_connection(NMSettingsPlugin *plugin, NMSettingsStorage *storage_x, GError
+     } else
+         operation_message = "deleted from disk";
+ 
++    #if WITH_NETPLAN
++    g_autofree gchar *netplan_id = NULL;
++    ssize_t           netplan_id_size = 0;
++
++    netplan_id = g_malloc0(strlen(previous_filename));
++    netplan_id_size = netplan_get_id_from_nm_filepath(previous_filename, ssid, netplan_id, strlen(previous_filename) - 1);
++    if (netplan_id_size > 0) {
++        _LOGI ("deleting netplan connection: %s", netplan_id);
++        netplan_delete_connection(netplan_id, NULL);
++        generate_netplan(NULL);
++    }
++    #endif
++
+     _LOGT("commit: deleted \"%s\", %s %s (%s%s%s%s)",
+           previous_filename,
+           storage->is_meta_data ? "meta-data" : "profile",
+diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c
+index 7c0e329..a91ee69 100644
+--- a/src/core/settings/plugins/keyfile/nms-keyfile-utils.c
++++ b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c
+@@ -399,3 +399,21 @@ nms_keyfile_utils_check_file_permissions(NMSKeyfileFiletype filetype,
+     NM_SET_OUT(out_st, st);
+     return TRUE;
+ }
++
++#if WITH_NETPLAN
++gboolean
++generate_netplan(const char* rootdir)
++{
++    /* TODO: call the io.netplan.Netplan.Generate() DBus method directly, after
++     * finding a way to pass the --root-dir parameter via DBus, to make it work
++     * inside NM's unit-tests where netplan needs to read & generate outside of
++     * /etc/netplan and /run/{systemd,NetworkManager} */
++    const gchar *argv[] = { "netplan", "generate", NULL , NULL, NULL };
++    if (rootdir) {
++        argv[2] = "--root-dir";
++        argv[3] = rootdir;
++    }
++    return g_spawn_sync(NULL, (gchar**)argv, NULL, G_SPAWN_SEARCH_PATH,
++                        NULL, NULL, NULL, NULL, NULL, NULL);
++}
++#endif
+diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-utils.h b/src/core/settings/plugins/keyfile/nms-keyfile-utils.h
+index 0fd83bd..9ed25d9 100644
+--- a/src/core/settings/plugins/keyfile/nms-keyfile-utils.h
++++ b/src/core/settings/plugins/keyfile/nms-keyfile-utils.h
+@@ -68,4 +68,8 @@ gboolean nms_keyfile_utils_check_file_permissions(NMSKeyfileFiletype filetype,
+                                                   struct stat       *out_st,
+                                                   GError           **error);
+ 
++#if WITH_NETPLAN
++gboolean generate_netplan(const char* rootdir);
++#endif
++
+ #endif /* __NMS_KEYFILE_UTILS_H__ */
+diff --git a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c
+index b1dd2e4..48b19e1 100644
+--- a/src/core/settings/plugins/keyfile/nms-keyfile-writer.c
++++ b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c
+@@ -12,6 +12,14 @@
+ #include <sys/stat.h>
+ #include <unistd.h>
+ 
++#if WITH_NETPLAN
++#include <net/if.h>
++#include <netplan/parse.h>
++#include <netplan/parse-nm.h>
++#include <netplan/util.h>
++#include <netplan/netplan.h>
++#endif
++
+ #include "libnm-core-intern/nm-keyfile-internal.h"
+ 
+ #include "nms-keyfile-utils.h"
+@@ -201,6 +209,9 @@ _internal_write_connection(NMConnection                   *connection,
+                            char                          **out_path,
+                            NMConnection                  **out_reread,
+                            gboolean                       *out_reread_same,
++                           #if WITH_NETPLAN
++                           const char                     *rootdir,
++                           #endif
+                            GError                        **error)
+ {
+     nm_auto_unref_keyfile GKeyFile *kf_file        = NULL;
+@@ -414,11 +425,161 @@ _internal_write_connection(NMConnection                   *connection,
+     if (existing_path && !existing_path_read_only && !nm_streq(path, existing_path))
+         unlink(existing_path);
+ 
++    #if WITH_NETPLAN
++    NetplanParser *npp      = NULL;
++    NetplanState  *np_state = NULL;
++
++    /* NETPLAN: write only non-temporary files to /etc/netplan/... */
++    if (!is_volatile && !is_nm_generated && !is_external &&
++        strstr(keyfile_dir, "/etc/NetworkManager/system-connections")) {
++        g_autofree gchar *ssid = g_key_file_get_string(kf_file, "wifi", "ssid", NULL);
++        g_autofree gchar *escaped_ssid = ssid ?
++                                         g_uri_escape_string(ssid, NULL, TRUE) : NULL;
++        g_autofree gchar *netplan_id = NULL;
++        ssize_t netplan_id_size = 0;
++        NetplanNetDefinition *netdef = NULL;
++        NetplanStateIterator state_iter;
++        const gchar* kf_path = path;
++
++        if (existing_path && strstr(existing_path, "system-connections/netplan-")) {
++            netplan_id = g_malloc0(strlen(existing_path));
++            netplan_id_size = netplan_get_id_from_nm_filepath(existing_path, ssid, netplan_id, strlen(existing_path) - 1);
++            if (netplan_id_size <= 0) {
++                g_free(netplan_id);
++                netplan_id = NULL;
++            }
++        }
++
++        if (netplan_id && existing_path) {
++            GFile* from = g_file_new_for_path(path);
++            GFile* to = g_file_new_for_path(existing_path);
++            g_file_copy(from, to, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL);
++            kf_path = existing_path;
++        }
++
++        // push keyfile into libnetplan for parsing (using existing_path, if available,
++        // to be able to extract the original netdef_id and override existing settings)
++        npp = netplan_parser_new();
++
++        if (!netplan_parser_load_keyfile(npp, kf_path, &local_err)) {
++            g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
++                         "netplan: YAML translation failed: %s", local_err->message);
++            goto netplan_parser_error;
++        }
++
++        np_state = netplan_state_new();
++        if (!netplan_state_import_parser_results(np_state, npp, &local_err)) {
++            g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
++                         "netplan: YAML validation failed: %s", local_err->message);
++            goto netplan_error;
++        }
++
++        netplan_state_iterator_init(np_state, &state_iter);
++        /* At this point we have a single netdef in the netplan state */
++        netdef = netplan_state_iterator_next(&state_iter);
++
++        if (!netdef) {
++            g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
++                         "netplan: Netplan state has no network definitions");
++            goto netplan_error;
++        }
++
++        if (!netplan_netdef_write_yaml(np_state, netdef, rootdir, &local_err)) {
++            g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
++                         "netplan: Failed to generate YAML: %s", local_err->message);
++            goto netplan_error;
++        }
++
++        /* Delete same connection-profile provided by legacy netplan plugin.
++         * TODO: drop legacy connection handling after 24.04 LTS */
++        g_autofree gchar* legacy_path = NULL;
++        legacy_path = g_strdup_printf("/etc/netplan/NM-%s.yaml", nm_connection_get_uuid (connection));
++        if (g_file_test(legacy_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
++            g_debug("Deleting legacy netplan connection: %s", legacy_path);
++            unlink(legacy_path);
++        }
++
++        /* Clear original keyfile in /etc/NetworkManager/system-connections/,
++         * we've written the /etc/netplan/*.yaml file instead. */
++        unlink(path);
++        if (!generate_netplan(rootdir)) {
++            g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
++                         "netplan generate failed");
++            goto netplan_error;
++        }
++
++        // Calculating the maximum space needed to store the new keyfile path
++        ssize_t path_size = strlen(path) + strlen(nm_connection_get_uuid(connection)) + IF_NAMESIZE + 1;
++        if (escaped_ssid)
++            path_size += strlen(escaped_ssid);
++        path_size += 50; // give some extra buffer, e.g. when going from  ConName to ConName.nmconnection
++
++        g_free(path);
++        path = g_malloc0(path_size);
++        path_size = netplan_netdef_get_output_filename(netdef, ssid, path, path_size);
++
++        if (path_size <= 0) {
++            g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
++                         "netplan: couldn't determine the keyfile path");
++            goto netplan_error;
++        }
++
++        if (rootdir) {
++            char* final_path = g_build_path(G_DIR_SEPARATOR_S, rootdir, path, NULL);
++            g_free(path);
++            path = final_path;
++        }
++
++        netplan_state_clear(&np_state);
++        netplan_parser_clear(&npp);
++
++        /* re-read again: this time the connection profile newly generated by netplan in /run/... */
++        if (   out_reread
++            || out_reread_same) {
++            gs_free_error GError *reread_error = NULL;
++
++            //XXX: why does the _from_keyfile function behave differently?
++            //reread = nms_keyfile_reader_from_keyfile (kf_file, path, NULL, profile_dir, FALSE, &reread_error);
++            reread = nms_keyfile_reader_from_file (path, profile_dir, NULL, NULL, NULL, NULL, NULL, NULL, &reread_error);
++
++            if (   !reread
++                || !nm_connection_normalize (reread, NULL, NULL, &reread_error)) {
++                nm_log_err (LOGD_SETTINGS, "BUG: the profile cannot be stored in keyfile format without becoming unusable: %s", reread_error->message);
++                g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
++                             "keyfile writer produces an invalid connection: %s",
++                             reread_error->message);
++                nm_assert_not_reached ();
++                return FALSE;
++            }
++
++            if (out_reread_same) {
++                reread_same = !!nm_connection_compare (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT);
++
++                nm_assert (reread_same == nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
++                nm_assert (reread_same == ({
++                                                gs_unref_hashtable GHashTable *_settings = NULL;
++
++                                                (   nm_connection_diff (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT, &_settings)
++                                                 && !_settings);
++                                           }));
++            }
++        }
++    }
++    #endif
++
+     NM_SET_OUT(out_reread, g_steal_pointer(&reread));
+     NM_SET_OUT(out_reread_same, reread_same);
+     NM_SET_OUT(out_path, g_steal_pointer(&path));
+ 
+     return TRUE;
++
++#if WITH_NETPLAN
++netplan_error:
++    netplan_state_clear(&np_state);
++netplan_parser_error:
++    netplan_parser_clear(&npp);
++    return FALSE;
++#endif
+ }
+ 
+ gboolean
+@@ -459,6 +620,9 @@ nms_keyfile_writer_connection(NMConnection                   *connection,
+                                       out_path,
+                                       out_reread,
+                                       out_reread_same,
++                                      #if WITH_NETPLAN
++                                      NULL,
++                                      #endif
+                                       error);
+ }
+ 
+@@ -472,6 +636,12 @@ nmtst_keyfile_writer_test_connection(NMConnection  *connection,
+                                      gboolean      *out_reread_same,
+                                      GError       **error)
+ {
++    #if WITH_NETPLAN
++    gchar *rootdir = g_strdup(keyfile_dir);
++    if (g_str_has_suffix (keyfile_dir, "/run/NetworkManager/system-connections")) {
++        rootdir[strlen(rootdir)-38] = '\0'; /* 38 = strlen("/run/NetworkManager/...") */
++    }
++    #endif
+     return _internal_write_connection(connection,
+                                       FALSE,
+                                       FALSE,
+@@ -491,5 +661,8 @@ nmtst_keyfile_writer_test_connection(NMConnection  *connection,
+                                       out_path,
+                                       out_reread,
+                                       out_reread_same,
++                                      #if WITH_NETPLAN
++                                      rootdir,
++                                      #endif
+                                       error);
+ }
+diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
+index 6b6913c..0679be5 100644
+--- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
++++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
+@@ -24,8 +24,15 @@
+ 
+ #include "nm-test-utils-core.h"
+ 
++#if WITH_NETPLAN
++#define TEST_KEYFILES_DIR_OLD   NM_BUILD_SRCDIR"/src/core/settings/plugins/keyfile/tests/keyfiles"
++#define TEST_SCRATCH_DIR_OLD    NM_BUILD_BUILDDIR"/src/core/settings/plugins/keyfile/tests/keyfiles"
++#define TEST_KEYFILES_DIR       TEST_KEYFILES_DIR_OLD"/run/NetworkManager/system-connections"
++#define TEST_SCRATCH_DIR        TEST_SCRATCH_DIR_OLD"/run/NetworkManager/system-connections"
++#else
+ #define TEST_KEYFILES_DIR NM_BUILD_SRCDIR "/src/core/settings/plugins/keyfile/tests/keyfiles"
+ #define TEST_SCRATCH_DIR  NM_BUILD_BUILDDIR "/src/core/settings/plugins/keyfile/tests/keyfiles"
++#endif
+ 
+ /*****************************************************************************/
+ 
+@@ -113,6 +120,11 @@ assert_reread_and_unlink(NMConnection *connection,
+ static void
+ assert_reread_same(NMConnection *connection, NMConnection *reread)
+ {
++    #if WITH_NETPLAN
++    // Netplan does some normalization already, so compare normalized connections
++    nm_connection_normalize (connection, NULL, NULL, NULL);
++    nm_connection_normalize (reread, NULL, NULL, NULL);
++    #endif
+     nmtst_assert_connection_verifies_without_normalization(reread);
+     nmtst_assert_connection_equals(connection, TRUE, reread, FALSE);
+ }
+@@ -852,6 +864,10 @@ test_write_wireless_connection(void)
+                  bssid,
+                  NM_SETTING_WIRELESS_SSID,
+                  ssid,
++                 #if WITH_NETPLAN
++                 //XXX: netplan uses explicit "infrastructure" mode
++                 NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
++                 #endif
+                  NM_SETTING_WIRED_MTU,
+                  1000,
+                  NULL);
+@@ -933,7 +949,12 @@ test_write_string_ssid(void)
+     nm_connection_add_setting(connection, NM_SETTING(s_wireless));
+ 
+     ssid = g_bytes_new(tmpssid, sizeof(tmpssid));
+-    g_object_set(s_wireless, NM_SETTING_WIRELESS_SSID, ssid, NULL);
++    g_object_set(s_wireless, NM_SETTING_WIRELESS_SSID, ssid,
++                 #if WITH_NETPLAN
++                 //XXX: netplan uses explicit "infrastructure" mode
++                 NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
++                 #endif
++                 NULL);
+     g_bytes_unref(ssid);
+ 
+     /* IP4 setting */
+@@ -1016,7 +1037,12 @@ test_write_intlist_ssid(void)
+     nm_connection_add_setting(connection, NM_SETTING(s_wifi));
+ 
+     ssid = g_bytes_new(tmpssid, sizeof(tmpssid));
+-    g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL);
++    g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid,
++                 #if WITH_NETPLAN
++                 //XXX: netplan uses explicit "infrastructure" mode
++                 NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
++                 #endif
++                 NULL);
+     g_bytes_unref(ssid);
+ 
+     /* IP4 setting */
+@@ -1116,7 +1142,12 @@ test_write_intlike_ssid(void)
+     nm_connection_add_setting(connection, NM_SETTING(s_wifi));
+ 
+     ssid = g_bytes_new(tmpssid, sizeof(tmpssid));
+-    g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL);
++    g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid,
++                 #if WITH_NETPLAN
++                 //XXX: netplan uses explicit "infrastructure" mode
++                 NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
++                 #endif
++                 NULL);
+     g_bytes_unref(ssid);
+ 
+     /* IP4 setting */
+@@ -1178,7 +1209,12 @@ test_write_intlike_ssid_2(void)
+     nm_connection_add_setting(connection, NM_SETTING(s_wifi));
+ 
+     ssid = g_bytes_new(tmpssid, sizeof(tmpssid));
+-    g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL);
++    g_object_set(s_wifi, NM_SETTING_WIRELESS_SSID, ssid,
++                 #if WITH_NETPLAN
++                 //XXX: netplan uses explicit "infrastructure" mode
++                 NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
++                 #endif
++                 NULL);
+     g_bytes_unref(ssid);
+ 
+     /* IP4 setting */
+@@ -2916,12 +2952,30 @@ main(int argc, char **argv)
+ 
+     nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT");
+ 
++    #if WITH_NETPLAN
++    if (g_mkdir_with_parents(TEST_SCRATCH_DIR, 0755) != 0) {
++        errsv = errno;
++        g_error("failure to create test directory \"%s\": %s",
++                TEST_SCRATCH_DIR,
++                nm_strerror_native(errsv));
++    }
++    // Prepare netplan test directories
++    g_mkdir_with_parents (TEST_SCRATCH_DIR_OLD"/etc/netplan", 0755);
++    g_mkdir_with_parents (TEST_SCRATCH_DIR_OLD"/run/NetworkManager", 0755);
++    g_mkdir_with_parents (TEST_KEYFILES_DIR_OLD"/run/NetworkManager", 0755);
++    // link "keyfiles/" to "run/NetworkManager/system-connections"
++    const gchar *args[] = { "/bin/ln", "-s", TEST_KEYFILES_DIR_OLD, TEST_KEYFILES_DIR, NULL };
++    g_spawn_sync(NULL, (gchar**)args, NULL, G_SPAWN_DEFAULT, NULL, NULL, NULL, NULL, NULL, NULL);
++    // clear netplan YAML config from previous runs
++    g_spawn_command_line_sync("/bin/sh -c 'rm -f " TEST_KEYFILES_DIR_OLD "/etc/netplan/*.yaml'", NULL, NULL, NULL, NULL);
++    #else
+     if (g_mkdir_with_parents(TEST_SCRATCH_DIR, 0755) != 0) {
+         errsv = errno;
+         g_error("failure to create test directory \"%s\": %s",
+                 TEST_SCRATCH_DIR,
+                 nm_strerror_native(errsv));
+     }
++    #endif
+ 
+     /* The tests */
+     g_test_add_func("/keyfile/test_read_valid_wired_connection", test_read_valid_wired_connection);
diff -pruN 1.52.0-1/debian/patches/netplan/0003-Allow-the-NetworkManager-daemon-to-write-to-lib-netp.patch 1.52.0-1ubuntu1/debian/patches/netplan/0003-Allow-the-NetworkManager-daemon-to-write-to-lib-netp.patch
--- 1.52.0-1/debian/patches/netplan/0003-Allow-the-NetworkManager-daemon-to-write-to-lib-netp.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/patches/netplan/0003-Allow-the-NetworkManager-daemon-to-write-to-lib-netp.patch	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,30 @@
+From: Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>
+Date: Mon, 23 Oct 2023 15:05:02 +0100
+Subject: Allow the NetworkManager daemon to write to /lib/netplan
+
+The systemd service file is setting ProtectSystem to true,
+which is giving Network Manager read only access to /usr. libnetplan
+currently requires rights to open files from /usr/lib/netplan with permission
+to write to them.
+
+Allow-list /usr/lib/netplan so libnetplan will not fail when called from the
+Network Manager's daemon.
+
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/netplan.io/+bug/2040153
+Forwarded: not-needed
+---
+ data/NetworkManager.service.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/data/NetworkManager.service.in b/data/NetworkManager.service.in
+index 8cd2ac8..193e925 100644
+--- a/data/NetworkManager.service.in
++++ b/data/NetworkManager.service.in
+@@ -23,6 +23,7 @@ CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SE
+ 
+ ProtectSystem=true
+ ProtectHome=read-only
++ReadWritePaths=/usr/lib/netplan
+ 
+ # We require file descriptors for DHCP etc. When activating many interfaces,
+ # the default limit of 1024 is easily reached.
diff -pruN 1.52.0-1/debian/patches/netplan/keyfile-update-test-for-expected-netplan-output.patch 1.52.0-1ubuntu1/debian/patches/netplan/keyfile-update-test-for-expected-netplan-output.patch
--- 1.52.0-1/debian/patches/netplan/keyfile-update-test-for-expected-netplan-output.patch	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/patches/netplan/keyfile-update-test-for-expected-netplan-output.patch	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,41 @@
+From: Jeremy Bicha <jeremy.bicha@canonical.com>
+Date: Wed, 19 Feb 2025 14:38:24 -0500
+Subject: keyfile: update test for expected netplan output
+
+0002-netplan-make-use-of-libnetplan-for-YAML-backend.patch
+says that netplan explicitly uses infrastructure mode
+so update the expected test output to match
+
+Forwarded: not-needed
+---
+ src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless | 1 +
+ src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c      | 2 --
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless
+index 2fc1509..b503c95 100644
+--- a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless
++++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless
+@@ -7,6 +7,7 @@ timestamp=305415219
+ 
+ [wifi]
+ bssid=AA:B9:A1:74:55:44
++mode=infrastructure
+ mtu=1000
+ ssid=1337
+ 
+diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
+index 0679be5..d6370ce 100644
+--- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
++++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
+@@ -864,10 +864,8 @@ test_write_wireless_connection(void)
+                  bssid,
+                  NM_SETTING_WIRELESS_SSID,
+                  ssid,
+-                 #if WITH_NETPLAN
+                  //XXX: netplan uses explicit "infrastructure" mode
+                  NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
+-                 #endif
+                  NM_SETTING_WIRED_MTU,
+                  1000,
+                  NULL);
diff -pruN 1.52.0-1/debian/patches/series 1.52.0-1ubuntu1/debian/patches/series
--- 1.52.0-1/debian/patches/series	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/patches/series	2025-03-03 17:49:02.000000000 +0000
@@ -1 +1,9 @@
 Force-online-state-with-unmanaged-devices.patch
+
+# Ubuntu patches
+Provide-access-to-some-of-NM-s-interfaces-to-whoopsie.patch
+Update-dnsmasq-parameters.patch
+netplan/0001-netplan-Adopt-buildsystems-for-Netplan-integration.patch
+netplan/0002-netplan-make-use-of-libnetplan-for-YAML-backend.patch
+netplan/0003-Allow-the-NetworkManager-daemon-to-write-to-lib-netp.patch
+netplan/keyfile-update-test-for-expected-netplan-output.patch
diff -pruN 1.52.0-1/debian/rules 1.52.0-1ubuntu1/debian/rules
--- 1.52.0-1/debian/rules	2025-02-28 17:58:44.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/rules	2025-03-03 17:49:02.000000000 +0000
@@ -2,6 +2,11 @@
 
 include /usr/share/dpkg/architecture.mk
 
+ifeq ($(shell dpkg-vendor --is Ubuntu && echo yes) $(DEB_HOST_ARCH), yes i386)
+   BUILD_PACKAGES += -Nnetwork-manager
+   NETPLAN += -Dnetplan=false
+endif
+
 # Disable lto here regardless of whether we enable the configure flag
 # https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1070
 export DEB_BUILD_MAINT_OPTIONS = hardening=+all optimize=-lto
@@ -11,7 +16,7 @@ export PYTHON=/usr/bin/python3
 PPPD_PLUGIN_DIR := $(shell dh_ppp --plugin-dir)
 
 %:
-	dh $@ --with ppp --without autoreconf --buildsystem=meson
+	dh $@ --with ppp $(BUILD_PACKAGES) --without autoreconf --buildsystem=meson
 
 override_dh_auto_configure:
 	dh_auto_configure -- \
@@ -55,8 +60,18 @@ override_dh_auto_configure:
 		-Dovs=false \
 		-Dqt=false \
 		-Debpf=false \
+		-Dtests=yes \
+		-Db_lto=true \
+		$(NETPLAN) \
 		-Dofono=false
 
+override_dh_install:
+	rm -vf $(CURDIR)/debian/tmp/etc/init.d/NetworkManager
+	dh_install
+
+override_dh_installinit:
+	dh_installinit --noscripts
+
 override_dh_makeshlibs:
 	dh_makeshlibs -X/usr/lib/$(DEB_HOST_MULTIARCH)/NetworkManager/ -X/usr/lib/pppd/
 
diff -pruN 1.52.0-1/debian/source_network-manager.py 1.52.0-1ubuntu1/debian/source_network-manager.py
--- 1.52.0-1/debian/source_network-manager.py	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/source_network-manager.py	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,95 @@
+"""Apport package hook for Network Manager
+
+(c) 2008 Canonical Ltd.
+Contributors:
+Matt Zimmerman <mdz@canonical.com>
+Martin Pitt <martin.pitt@canonical.com>
+Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Thomas Bechtold <thomasbechtold@jpberlin.de>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
+the full text of the license.
+"""
+
+import os
+import subprocess
+from apport.hookutils import *
+
+
+def _network_interfaces():
+    interfaces = []
+    output = command_output(["ls", "-1", "/sys/class/net"])
+    for device in output.split("\n"):
+        interfaces.append(device)
+
+    return interfaces
+
+
+def _device_details(device):
+    details = command_output(
+        ["udevadm", "info", "--query=all", "--path", "/sys/class/net/%s" % device]
+    )
+
+    # add the only extra thing of use from hal we don't get from udev.
+    details = details + "\nX: INTERFACE_MAC="
+    details = details + command_output(["cat", "/sys/class/net/%s/address" % device])
+    return details
+
+
+def add_info(report, ui=None):
+    attach_network(report)
+    attach_wifi(report)
+
+    # this is the old config file (still read by NM if available)
+    attach_file_if_exists(
+        report, "/etc/NetworkManager/nm-system-settings.conf", "nm-system-settings.conf"
+    )
+
+    # the new default config file
+    attach_file_if_exists(
+        report, "/etc/NetworkManager/NetworkManager.conf", "NetworkManager.conf"
+    )
+
+    # attach NetworkManager.state: it gives us good hints in rfkill-related bugs.
+    attach_file_if_exists(
+        report, "/var/lib/NetworkManager/NetworkManager.state", "NetworkManager.state"
+    )
+
+    for interface in _network_interfaces():
+        key = "NetDevice.%s" % interface
+        report[key] = _device_details(interface)
+
+    interesting_modules = {
+        "ndiswrapper": "driver-ndiswrapper",
+        "ath_hal": "driver-madwifi",
+        "b44": "driver-b44",
+    }
+    interesting_modules_loaded = []
+    tags = []
+    for line in open("/proc/modules"):
+        module = line.split()[0]
+        if module in interesting_modules:
+            tags.append(interesting_modules[module])
+            interesting_modules_loaded.append(module)
+
+    if interesting_modules_loaded:
+        report["InterestingModules"] = " ".join(interesting_modules_loaded)
+        report.setdefault("Tags", "")
+        report["Tags"] += " " + " ".join(tags)
+
+    # add output of nmcli
+    report["nmcli-nm"] = command_output(["nmcli", "-f", "all", "gen"])
+    report["nmcli-dev"] = command_output(["nmcli", "-f", "all", "dev"])
+    report["nmcli-con"] = command_output(["nmcli", "-f", "all", "con"])
+
+
+## Only for debugging ##
+if __name__ == "__main__":
+    report = {}
+    report["CrashDB"] = "ubuntu"
+    add_info(report, None)
+    for key in report:
+        print("%s: %s" % (key, report[key]))
diff -pruN 1.52.0-1/debian/tests/Makefile 1.52.0-1ubuntu1/debian/tests/Makefile
--- 1.52.0-1/debian/tests/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/Makefile	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,8 @@
+
+obj-m += fake-rfkill.o
+
+fake-rfkill:
+	make -C /lib/modules/$(shell uname -r)/build KBUILD_SRC=/lib/modules/$(shell uname -r)/build M=$(shell pwd)/debian/tests
+
+clean-rfkill:
+	make -C /lib/modules/$(shell uname -r)/build KBUILD_SRC=/lib/modules/$(shell uname -r)/build M=$(shell pwd)/debian/tests clean
diff -pruN 1.52.0-1/debian/tests/base.py 1.52.0-1ubuntu1/debian/tests/base.py
--- 1.52.0-1/debian/tests/base.py	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/base.py	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,673 @@
+"""
+Base class for network related tests.
+
+This provides test ethernet devices with veth, functions to start dnsmasq,
+and some utility functions.
+"""
+
+__author__ = "Martin Pitt <martin.pitt@ubuntu.com>"
+__copyright__ = "(C) 2013-2025 Canonical Ltd."
+__license__ = "GPL v2 or later"
+
+import ctypes
+import functools
+import os
+import os.path
+import shutil
+import subprocess
+import tempfile
+import time
+import traceback
+import unittest
+from glob import glob
+
+import gi
+
+gi.require_version("NM", "1.0")
+from gi.repository import NM, Gio, GLib
+
+# If True, NetworkManager logs directly to stdout, to watch logs in real time
+NM_LOG_STDOUT = os.getenv("NM_LOG_STDOUT", False)
+
+# avoid accidentally destroying any real config
+os.environ["GSETTINGS_BACKEND"] = "memory"
+
+def run_in_subprocess(fn):
+    """Decorator for running fn in a child process"""
+
+    @functools.wraps(fn)
+    def wrapped(*args, **kwargs):
+        # args[0] is self
+        args[0].wrap_process(fn, *args, **kwargs)
+
+    return wrapped
+
+def wait_nm_online():
+    tries = 5
+    while tries > 0 and subprocess.call(['nm-online', '-qs']) != 0:
+        time.sleep(1)
+        tries = tries - 1
+
+def set_up_module():
+    # unshare the mount namespace, so that our tmpfs mounts are guaranteed to get
+    # cleaned up, and don't influence the production system
+    libc6 = ctypes.cdll.LoadLibrary("libc.so.6")
+    assert (
+        libc6.unshare(ctypes.c_int(0x00020000)) == 0
+    ), "failed to unshare mount namespace"
+
+    # stop system-wide NetworkManager to avoid interfering with tests
+    subprocess.check_call(['systemctl', 'stop', 'NetworkManager.service'])
+
+def tear_down_module():
+    # Make sure the management network stays up-and-running.
+    if os.path.exists('/etc/systemd/network/20-wired.network'):
+        subprocess.check_call(['systemctl', 'restart', 'systemd-networkd.service'])
+    else:
+        print("WARNING: mgmt network config (20-wired.network) not found. "
+              "Skipping restart of systemd-networkd.service ...")
+
+
+class NetworkTestBase(unittest.TestCase):
+    """Common functionality for network test cases
+
+    setUp() creates two test veth devices (self.dev_e_ap and elf.dev_e_client).
+    Each test should call self.setup_eth() with the desired configuration.
+    """
+
+    @classmethod
+    def setUpClass(klass):
+        # check availability of programs, and cleanly skip test if they are not
+        # available
+        for program in ["dnsmasq"]:
+            if shutil.which(program) is None:
+                raise SystemError("%s is required for this test suite, but not available" % program)
+
+        # Try to keep autopkgtest's management network (eth0/ens3) up and
+        # configured. It should be running all the time, independently via
+        # systemd-networkd, potentially overriding 10-netplan-*.network config.
+        os.makedirs('/etc/systemd/network', exist_ok=True)
+        with open('/etc/systemd/network/20-wired.network', 'w') as f:
+            f.write('[Match]\nName=eth0 en*\n\n[Network]\nDHCP=yes\nKeepConfiguration=yes')
+        subprocess.check_call(['systemctl', 'restart', 'systemd-networkd.service'])
+
+    @classmethod
+    def tearDownClass(klass):
+        os.remove("/run/udev/rules.d/99-nm-veth-test.rules")
+
+    @classmethod
+    def create_devices(klass):
+        """Create Access Point and Client veth devices"""
+
+        klass.dev_e_ap = "veth42"
+        klass.dev_e_client = "eth42"
+
+        if os.path.exists("/sys/class/net/" + klass.dev_e_client):
+            raise SystemError("%s interface already exists" % klass.dev_e_client)
+
+        # ensure NM can manage our fake eths
+        os.makedirs("/run/udev/rules.d", exist_ok=True)
+        with open("/run/udev/rules.d/99-nm-veth-test.rules", "w") as f:
+            f.write(
+                'ENV{ID_NET_DRIVER}=="veth", ENV{INTERFACE}=="%s", ENV{NM_UNMANAGED}="0"\n'
+                % klass.dev_e_client
+            )
+        subprocess.check_call(["udevadm", "control", "--reload"])
+
+        # create virtual ethernet devs
+        subprocess.check_call(
+            [
+                "ip",
+                "link",
+                "add",
+                "name",
+                klass.dev_e_client,
+                "type",
+                "veth",
+                "peer",
+                "name",
+                klass.dev_e_ap,
+            ]
+        )
+
+        # determine and store MAC addresses
+        # Creation of the veths introduces a race with newer versions of
+        # systemd, as it  will change the initial MAC address after the device
+        # was created and networkd took control. Give it some time, so we read
+        # the correct MAC address
+        time.sleep(1)
+        with open("/sys/class/net/%s/address" % klass.dev_e_ap) as f:
+            klass.mac_e_ap = f.read().strip().upper()
+        with open("/sys/class/net/%s/address" % klass.dev_e_client) as f:
+            klass.mac_e_client = f.read().strip().upper()
+
+    @classmethod
+    def shutdown_devices(klass):
+        """Remove test wlan devices"""
+
+        subprocess.check_call(["ip", "link", "del", "dev", klass.dev_e_ap])
+        klass.dev_e_ap = None
+        klass.dev_e_client = None
+
+    def run(self, result=None):
+        """Show log files on failed tests"""
+
+        if result:
+            orig_err_fail = len(result.errors) + len(result.failures)
+        super().run(result)
+        if hasattr(self, "workdir"):
+            logs = glob(os.path.join(self.workdir, "*.log"))
+            if result and len(result.errors) + len(result.failures) > orig_err_fail:
+                for log_file in logs:
+                    with open(log_file) as f:
+                        print(
+                            "\n----- %s -----\n%s\n------\n"
+                            % (os.path.basename(log_file), f.read())
+                        )
+
+            # clean up log files, so that we don't see ones from previous tests
+            for log_file in logs:
+                os.unlink(log_file)
+
+    def setUp(self):
+        """Create test devices and workdir"""
+
+        self.create_devices()
+        self.addCleanup(self.shutdown_devices)
+        self.workdir_obj = tempfile.TemporaryDirectory()
+        self.workdir = self.workdir_obj.name
+
+        # create static entropy file to avoid draining/blocking on /dev/random
+        self.entropy_file = os.path.join(self.workdir, "entropy")
+        with open(self.entropy_file, "wb") as f:
+            f.write(b"012345678901234567890")
+
+    def setup_eth(self, ipv6_mode, start_dnsmasq=True):
+        """Set up simulated ethernet router
+
+        On self.dev_e_ap, run dnsmasq according to ipv6_mode, see
+        start_dnsmasq().
+
+        This is torn down automatically at the end of the test.
+        """
+        # give our router an IP
+        subprocess.check_call(["ip", "a", "flush", "dev", self.dev_e_ap])
+        if ipv6_mode is not None:
+            subprocess.check_call(
+                ["ip", "a", "add", "2600::1/64", "dev", self.dev_e_ap]
+            )
+        else:
+            subprocess.check_call(
+                ["ip", "a", "add", "192.168.5.1/24", "dev", self.dev_e_ap]
+            )
+        subprocess.check_call(["ip", "link", "set", self.dev_e_ap, "up"])
+        # we don't really want to up the client iface already, but veth doesn't
+        # work otherwise (no link detected)
+        subprocess.check_call(["ip", "link", "set", self.dev_e_client, "up"])
+
+        if start_dnsmasq:
+            self.start_dnsmasq(ipv6_mode, self.dev_e_ap)
+
+    def wrap_process(self, fn, *args, **kwargs):
+        """Run a test method in a separate process.
+
+        Run test method fn(*args, **kwargs) in a child process. If that raises
+        any exception, it gets propagated to the main process and
+        wrap_process() fails with that exception.
+        """
+        # exception from subprocess is propagated through this file
+        exc_path = os.path.join(self.workdir, "exc")
+        try:
+            os.unlink(exc_path)
+        except OSError:
+            pass
+
+        pid = os.fork()
+
+        # run the actual test in the child
+        if pid == 0:
+            # short-circuit tearDownClass(), as this will be done by the parent
+            # process
+            self.addCleanup(os._exit, 0)
+            try:
+                fn(*args, **kwargs)
+            except:
+                with open(exc_path, "w") as f:
+                    f.write(traceback.format_exc())
+                raise
+        else:
+            # get success/failure state from child
+            os.waitpid(pid, 0)
+            # propagate exception
+            if os.path.exists(exc_path):
+                with open(exc_path) as f:
+                    self.fail(f.read())
+
+    #
+    # Internal implementation details
+    #
+
+    @classmethod
+    def poll_text(klass, logpath, string, timeout=50):
+        """Poll log file for a given string with a timeout.
+
+        Timeout is given in deciseconds.
+        """
+        log = ""
+        while timeout > 0:
+            if os.path.exists(logpath):
+                break
+            timeout -= 1
+            time.sleep(0.1)
+        assert timeout > 0, "Timed out waiting for file %s to appear" % logpath
+
+        with open(logpath) as f:
+            while timeout > 0:
+                line = f.readline()
+                if line:
+                    log += line
+                    if string in line:
+                        break
+                    continue
+                timeout -= 1
+                time.sleep(0.1)
+
+        assert (
+            timeout > 0
+        ), 'Timed out waiting for "%s":\n------------\n%s\n-------\n' % (string, log)
+
+    def start_dnsmasq(self, ipv6_mode, iface):
+        """Start dnsmasq.
+
+        If ipv6_mode is None, IPv4 is set up with DHCP. If it is not None, it
+        must be a valid dnsmasq mode, i. e. a combination of "ra-only",
+        "slaac", "ra-stateless", and "ra-names". See dnsmasq(8).
+        """
+        if ipv6_mode is None:
+            dhcp_range = "192.168.5.10,192.168.5.200"
+        else:
+            dhcp_range = "2600::10,2600::20"
+            if ipv6_mode:
+                dhcp_range += "," + ipv6_mode
+
+        self.dnsmasq_log = os.path.join(self.workdir, "dnsmasq.log")
+        lease_file = os.path.join(self.workdir, "dnsmasq.leases")
+
+        p = subprocess.Popen(
+            [
+                "dnsmasq",
+                "--keep-in-foreground",
+                "--log-queries",
+                "--log-facility=" + self.dnsmasq_log,
+                "--conf-file=/dev/null",
+                "--dhcp-leasefile=" + lease_file,
+                "--bind-interfaces",
+                "--interface=" + iface,
+                "--except-interface=lo",
+                "--enable-ra",
+                "--dhcp-range=" + dhcp_range,
+            ]
+        )
+        self.addCleanup(p.wait)
+        self.addCleanup(p.terminate)
+
+        if ipv6_mode is not None:
+            self.poll_text(self.dnsmasq_log, "IPv6 router advertisement enabled")
+        else:
+            self.poll_text(self.dnsmasq_log, "DHCP, IP range")
+
+    def filtered_active_connections(self) -> list:
+        # Ignore the 'lo' connection, active since NM 1.42:
+        # https://networkmanager.dev/blog/networkmanager-1-42/#managing-the-loopback-interface
+        active_connections = [c for c in self.nmclient.get_active_connections() if c.get_id() != 'lo']
+        return active_connections
+
+    def start_nm(self, wait_iface=None, auto_connect=True, managed_devices=None):
+        """Start NetworkManager and initialize client object
+
+        If wait_iface is given, wait until NM recognizes that interface.
+        Otherwise, just wait until NM has initialized (for coldplug mode).
+
+        If auto_connect is False, set the "no-auto-default=*" option to avoid
+        auto-connecting to wired devices.
+        """
+        # mount tmpfses over system directories, to avoid destroying the
+        # production configuration, and isolating tests from each other
+        if not os.path.exists("/run/NetworkManager"):
+            os.mkdir("/run/NetworkManager")
+        for d in [
+            "/etc/NetworkManager",
+            "/var/lib/NetworkManager",
+            "/run/NetworkManager",
+            "/etc/netplan",
+        ]:
+            if os.path.exists(d):
+                subprocess.check_call(["mount", "-n", "-t", "tmpfs", "none", d])
+                self.addCleanup(subprocess.call, ["umount", d])
+        os.mkdir("/etc/NetworkManager/system-connections")
+
+        # create local configuration; this allows us to have full control, and
+        # we also need to blacklist the AP device so that NM does not tear it
+        # down; we also blacklist any existing real interface to avoid
+        # interfering with it, and for getting predictable results
+        blacklist = ""
+        if not managed_devices:
+            managed_devices = [self.dev_e_client]
+        for iface in os.listdir("/sys/class/net"):
+            if iface == "bonding_masters":
+                continue
+            if iface not in managed_devices:
+                with open("/sys/class/net/%s/address" % iface) as f:
+                    if blacklist:
+                        blacklist += ";"
+                    blacklist += "mac:%s" % f.read().strip()
+
+        conf = os.path.join(self.workdir, "NetworkManager.conf")
+        extra_main = ""
+        if not auto_connect:
+            extra_main += "no-auto-default=*\n"
+
+        with open(conf, "w") as f:
+            f.write(
+                "[main]\nplugins=keyfile\n%s\n[keyfile]\nunmanaged-devices=%s\n"
+                % (extra_main, blacklist)
+            )
+
+        if NM_LOG_STDOUT:
+            f_log = None
+        else:
+            log = os.path.join(self.workdir, "NetworkManager.log")
+            f_log = os.open(log, os.O_CREAT | os.O_WRONLY | os.O_SYNC)
+
+        # build NM command line
+        argv = ["NetworkManager", "--log-level=debug", "--debug", "--config=" + conf]
+        # allow specifying extra arguments
+        argv += os.environ.get("NM_TEST_DAEMON_ARGS", "").strip().split()
+
+        p = subprocess.Popen(argv, stdout=f_log, stderr=subprocess.STDOUT)
+        wait_nm_online()
+        # automatically terminate process at end of test case
+        self.addCleanup(p.wait)
+        self.addCleanup(p.terminate)
+        self.addCleanup(self.shutdown_connections)
+
+        if NM_LOG_STDOUT:
+            # let it initialize, then print a marker
+            time.sleep(1)
+            print("******* NM initialized *********\n\n")
+        else:
+            self.addCleanup(os.close, f_log)
+
+            # this should be fast, give it 2 s to initialize
+            if wait_iface:
+                self.poll_text(log, "manager: (%s): new" % wait_iface, timeout=100)
+
+        self.nmclient = NM.Client.new()
+        self.assertTrue(self.nmclient.networking_get_enabled())
+        self.assertTrue(self.nmclient.get_nm_running())
+
+        # determine device objects
+        for d in self.nmclient.get_devices():
+            if d.props.interface == self.dev_e_client:
+                self.assertEqual(d.get_device_type(), NM.DeviceType.VETH)
+                self.assertEqual(d.get_driver(), "veth")
+                self.assertEqual(d.get_hw_address(), self.mac_e_client)
+                self.nmdev_e = d
+
+        self.assertTrue(
+            hasattr(self, "nmdev_e"), "Could not determine eth client NM device"
+        )
+
+        self.process_glib_events()
+
+    def shutdown_connections(self):
+        """Shut down all active NM connections."""
+
+        def deactivate_cb(client, res, data):
+            if not client.deactivate_connection_finish(res):
+                print("WARNING: Failed to deactivate connection %s" % data.get_id(), flush=True)
+
+        if NM_LOG_STDOUT:
+            print("\n\n******* Shutting down NM connections *********")
+
+        # remove all created connections. Ignoring the loopback interface, which
+        # is actively managed since NM 1.42:
+        # https://networkmanager.dev/blog/networkmanager-1-42/#managing-the-loopback-interface
+        for active_conn in self.filtered_active_connections():
+            self.nmclient.deactivate_connection_async(active_conn, None,
+                                                      deactivate_cb, active_conn)
+        try:
+            # Only a single connection for the loopback interface might be left
+            self.assertEventually(
+                lambda: len(self.filtered_active_connections()) == 0,
+                timeout=100
+            )
+        except AssertionError as e:
+            # Log message is hidden by default, when called from an "addCleanup"
+            # hook. So let's log it explicitly:
+            print(f"AssertionError: get_active_connections not empty: {e}")
+            print("Active connections: %s" %
+                  list(map(lambda c: c.get_id(), self.nmclient.get_active_connections())))
+            raise
+
+        # verify that NM properly deconfigures the devices
+        try:
+            self.assert_iface_down(self.dev_e_client)
+        except AssertionError as e:
+            # Log message is hidden by default, when called from an "addCleanup"
+            # hook. So let's log it explicitly:
+            print(f"AssertionError: {e}")
+            raise
+
+    @classmethod
+    def process_glib_events(klass):
+        """Process pending GLib main loop events"""
+
+        context = GLib.MainContext.default()
+        while context.iteration(False):
+            pass
+
+    def assertEventually(self, condition, message=None, timeout=50):
+        """Assert that condition function eventually returns True.
+
+        timeout is in deciseconds, defaulting to 50 (5 seconds). message is
+        printed on failure.
+        """
+        while timeout >= 0:
+            self.process_glib_events()
+            if condition():
+                break
+            if timeout % 10 == 0:  # indicate progress
+                print(".", end="", flush=True)
+            timeout -= 1
+            time.sleep(0.1)
+        else:
+            self.fail(message or "timed out waiting for " + str(condition))
+
+    def assert_iface_down(self, iface):
+        """Assert that client interface is down"""
+
+        out = subprocess.check_output(
+            ["ip", "a", "show", "dev", iface], universal_newlines=True
+        )
+        self.assertNotIn("inet 192", out)
+        self.assertNotIn("inet6 2600", out)
+
+    def assert_iface_up(self, iface, expected_ip_a=None, unexpected_ip_a=None):
+        """Assert that client interface is up"""
+
+        out = subprocess.check_output(
+            ["ip", "a", "show", "dev", iface], universal_newlines=True
+        )
+        self.assertIn("state UP", out)
+        if expected_ip_a:
+            for r in expected_ip_a:
+                self.assertRegex(out, r)
+        if unexpected_ip_a:
+            for r in unexpected_ip_a:
+                self.assertNotRegex(out, r)
+
+    def conn_from_active_conn(self, active_conn):
+        """Get NMConnection object for an NMActiveConnection object"""
+
+        # this sometimes takes a second try, when the corresponding
+        # NMConnection object is not yet available
+        tries = 3
+        while tries > 0:
+            self.process_glib_events()
+            path = active_conn.get_connection().get_path()
+            for dev in active_conn.get_devices():
+                for c in dev.get_available_connections():
+                    if c.get_path() == path:
+                        return c
+            time.sleep(0.1)
+            tries -= 1
+
+        self.fail("Could not find NMConnection object for %s" % path)
+
+    def check_low_level_config(self, iface, ipv6_mode, ip6_privacy):
+        """Check actual hardware state with ip/iw after being connected"""
+
+        # list of expected regexps in "ip a" output
+        expected_ip_a = []
+        unexpected_ip_a = []
+
+        if ipv6_mode is not None:
+            if ipv6_mode in ("", "slaac"):
+                # has global address from our DHCP server
+                expected_ip_a.append("inet6 2600::[0-9a-f]+/")
+            else:
+                # has address with our prefix and MAC
+                expected_ip_a.append(
+                    r"inet6 2600::[0-9a-f:]+/64 scope global (?:tentative )?(?:mngtmpaddr )?(?:noprefixroute )?(dynamic|\n\s*valid_lft forever preferred_lft forever)"
+                )
+                # has address with our prefix and random IP (Privacy
+                # Extension), if requested
+                priv_re = r"inet6 2600:[0-9a-f:]+/64 scope global temporary (?:tentative )?(?:mngtmpaddr )?dynamic"
+                if ip6_privacy in (
+                    NM.SettingIP6ConfigPrivacy.PREFER_TEMP_ADDR,
+                    NM.SettingIP6ConfigPrivacy.PREFER_PUBLIC_ADDR,
+                ):
+                    expected_ip_a.append(priv_re)
+                else:
+                    # FIXME: add a negative test here
+                    pass
+                    # unexpected_ip_a.append(priv_re)
+
+            # has a link-local address
+            expected_ip_a.append(r"inet6 fe80::[0-9a-f:]+/64 scope link")
+        else:
+            expected_ip_a.append(r"inet 192.168.5.\d+/24")
+
+        self.assert_iface_up(iface, expected_ip_a, unexpected_ip_a)
+
+    #
+    # Common test code
+    #
+
+    # libnm-glib has a lot of internal persistent state (private D-BUS
+    # connections and such); as it is very brittle and hard to track down
+    # all remaining references to any NM* object after a test, we rather
+    # run each test in a separate subprocess
+    @run_in_subprocess
+    def do_test(self, ipv6_mode, ip6_privacy=None, auto_connect=True):
+        """Actual test code, parameterized for the particular test case"""
+
+        self.setup_eth(ipv6_mode)
+        self.start_nm(self.dev_e_client, auto_connect=auto_connect)
+
+        ip4_method = NM.SETTING_IP4_CONFIG_METHOD_DISABLED
+        ip6_method = NM.SETTING_IP6_CONFIG_METHOD_IGNORE
+        if ipv6_mode is None:
+            ip4_method = NM.SETTING_IP4_CONFIG_METHOD_AUTO
+        else:
+            ip6_method = NM.SETTING_IP6_CONFIG_METHOD_AUTO
+
+        if auto_connect:
+            # ethernet should auto-connect quickly without an existing defined connection
+            self.assertEventually(
+                lambda: len(self.filtered_active_connections()) > 0,
+                "timed out waiting for active connections",
+                timeout=100,
+            )
+            active_conn = self.filtered_active_connections()[0]
+        else:
+            # auto-connection was disabled, set up manual connection
+            partial_conn = NM.SimpleConnection.new()
+            partial_conn.add_setting(NM.SettingIP4Config(method=ip4_method))
+            if ip6_privacy is not None:
+                partial_conn.add_setting(
+                    NM.SettingIP6Config(ip6_privacy=ip6_privacy, method=ip6_method)
+                )
+
+            ml = GLib.MainLoop()
+            self.cb_conn = None
+            self.cancel = Gio.Cancellable()
+            self.timeout_tag = 0
+
+            def add_activate_cb(client, res, data):
+                if self.timeout_tag > 0:
+                    GLib.source_remove(self.timeout_tag)
+                    self.timeout_tag = 0
+                try:
+                    self.cb_conn = self.nmclient.add_and_activate_connection_finish(res)
+                except gi.repository.GLib.Error as e:
+                    # Check if the error is "Operation was cancelled"
+                    if e.domain != "g-io-error-quark" or e.code != 19:
+                        self.fail(
+                            "add_and_activate_connection failed: %s (%s, %d)"
+                            % (e.message, e.domain, e.code)
+                        )
+                ml.quit()
+
+            def timeout_cb():
+                self.timeout_tag = -1
+                self.cancel.cancel()
+                ml.quit()
+                return GLib.SOURCE_REMOVE
+
+            self.nmclient.add_and_activate_connection_async(
+                partial_conn, self.nmdev_e, None, self.cancel, add_activate_cb, None
+            )
+            self.timeout_tag = GLib.timeout_add_seconds(300, timeout_cb)
+            ml.run()
+            if self.timeout_tag < 0:
+                self.timeout_tag = 0
+                self.fail("Main loop for adding connection timed out!")
+            self.assertNotEqual(self.cb_conn, None)
+            active_conn = self.cb_conn
+            self.cb_conn = None
+
+        # we are usually ACTIVATING at this point; wait for completion
+        self.assertEventually(
+            lambda: active_conn.get_state() == NM.ActiveConnectionState.ACTIVATED,
+            "timed out waiting for %s to get activated" % active_conn.get_connection(),
+            timeout=150,
+        )
+        self.assertEqual(self.nmdev_e.get_state(), NM.DeviceState.ACTIVATED)
+
+        conn = self.conn_from_active_conn(active_conn)
+        self.assertTrue(conn.verify())
+
+        # check NMActiveConnection object
+        self.assertIn(
+            active_conn.get_uuid(),
+            [c.get_uuid() for c in self.filtered_active_connections()],
+        )
+        self.assertEqual(
+            [d.get_udi() for d in active_conn.get_devices()], [self.nmdev_e.get_udi()]
+        )
+
+        # for IPv6, check privacy setting
+        if ipv6_mode is not None:
+            assert (
+                ip6_privacy is not None
+            ), "for IPv6 tests you need to specify ip6_privacy flag"
+            if ip6_privacy not in (
+                NM.SettingIP6ConfigPrivacy.UNKNOWN,
+                NM.SettingIP6ConfigPrivacy.DISABLED,
+            ):
+                ip6_setting = conn.get_setting_ip6_config()
+                self.assertEqual(ip6_setting.props.ip6_privacy, ip6_privacy)
+
+        self.check_low_level_config(self.dev_e_client, ipv6_mode, ip6_privacy)
diff -pruN 1.52.0-1/debian/tests/base_wifi.py 1.52.0-1ubuntu1/debian/tests/base_wifi.py
--- 1.52.0-1/debian/tests/base_wifi.py	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/base_wifi.py	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,607 @@
+"""
+Base class for network related tests.
+
+This provides fake wifi devices with mac80211_hwsim and hostapd, test ethernet
+devices with veth, utility functions to start wpasupplicant, dnsmasq, get/set
+rfkill status, and some utility functions.
+"""
+
+__author__ = "Martin Pitt <martin.pitt@ubuntu.com>"
+__copyright__ = "(C) 2013-2025 Canonical Ltd."
+__license__ = "GPL v2 or later"
+
+import ctypes
+import functools
+import os
+import os.path
+import re
+import shutil
+import subprocess
+import sys
+import time
+from glob import glob
+
+import gi
+
+import base
+
+gi.require_version("NM", "1.0")
+from gi.repository import NM, Gio, GLib
+
+# If True, NetworkManager logs directly to stdout, to watch logs in real time
+NM_LOG_STDOUT = os.getenv("NM_LOG_STDOUT", False)
+
+# avoid accidentally destroying any real config
+os.environ["GSETTINGS_BACKEND"] = "memory"
+
+def run_in_subprocess(fn):
+    """Decorator for running fn in a child process"""
+
+    @functools.wraps(fn)
+    def wrapped(*args, **kwargs):
+        # args[0] is self
+        args[0].wrap_process(fn, *args, **kwargs)
+
+    return wrapped
+
+def wait_nm_online():
+    tries = 5
+    while tries > 0 and subprocess.call(['nm-online', '-qs']) != 0:
+        time.sleep(1)
+        tries = tries - 1
+
+def set_up_module():
+    # unshare the mount namespace, so that our tmpfs mounts are guaranteed to get
+    # cleaned up, and don't influence the production system
+    libc6 = ctypes.cdll.LoadLibrary("libc.so.6")
+    assert (
+        libc6.unshare(ctypes.c_int(0x00020000)) == 0
+    ), "failed to unshare mount namespace"
+
+    # stop system-wide NetworkManager to avoid interfering with tests
+    subprocess.check_call(['systemctl', 'stop', 'NetworkManager.service'])
+
+def tear_down_module():
+    # Make sure the management network stays up-and-running.
+    if os.path.exists('/etc/systemd/network/20-wired.network'):
+        subprocess.check_call(['systemctl', 'restart', 'systemd-networkd.service'])
+    else:
+        print("WARNING: mgmt network config (20-wired.network) not found. "
+              "Skipping restart of systemd-networkd.service ...")
+
+
+class WifiAuthentication():
+    def __init__(self):
+        self.wpa_settings = None
+        self.wpa_eap_settings = None
+        self.setting_name = None
+        self.needed_secrets = None
+
+        self.tmpdir = '/tmp/hostapd'
+        shutil.rmtree(self.tmpdir, ignore_errors=True)
+
+    @property
+    def auth_settings(self):
+        return self.wpa_settings
+
+    @property
+    def auth_eap_settings(self):
+        return self.wpa_eap_settings
+
+
+class WifiAuthenticationWPAPSK(WifiAuthentication):
+    def __init__(self, psk):
+        super().__init__()
+        self.wpa_settings = NM.SettingWirelessSecurity.new()
+        self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk")
+        self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_PSK, psk)
+
+        self.setting_name = NM.SETTING_WIRELESS_SECURITY_SETTING_NAME
+        self.needed_secrets = [NM.SETTING_WIRELESS_SECURITY_PSK]
+
+
+class WifiAuthenticationWPAEAP(WifiAuthentication):
+    def __init__(self, modes, phase2, identity, password, client_cert=False):
+        super().__init__()
+
+        self.make_certs()
+
+        self.wpa_settings = NM.SettingWirelessSecurity.new()
+        self.wpa_settings.set_property(NM.SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap")
+
+        self.wpa_eap_settings = NM.Setting8021x.new()
+        self.wpa_eap_settings.set_property(NM.SETTING_802_1X_EAP, modes)
+
+        self.wpa_eap_settings.set_property(NM.SETTING_802_1X_IDENTITY, identity)
+
+        if password:
+            self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PASSWORD, password)
+
+        if phase2 == 'tls':
+            self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PHASE2_AUTHEAP, phase2)
+        else:
+            self.wpa_eap_settings.set_property(NM.SETTING_802_1X_PHASE2_AUTH, phase2)
+
+        if client_cert:
+            # Certificate paths must start with file:// and be null terminated
+            # See src/libnmc-setting/settings-docs.h
+            self.wpa_eap_settings.set_property(
+                    NM.SETTING_802_1X_CA_CERT,
+                    GLib.Bytes(f'file://{self.tmpdir}/pki/ca.crt\0'.encode()))
+            self.wpa_eap_settings.set_property(
+                    NM.SETTING_802_1X_CLIENT_CERT,
+                    GLib.Bytes(f'file://{self.tmpdir}/pki/issued/client.crt\0'.encode()))
+            self.wpa_eap_settings.set_property(
+                    NM.SETTING_802_1X_PRIVATE_KEY,
+                    GLib.Bytes(f'file://{self.tmpdir}/pki/private/client.key\0'.encode()))
+            self.wpa_eap_settings.set_property(
+                    NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD, 'passw0rd')
+
+        self.setting_name = NM.SETTING_802_1X_SETTING_NAME
+        self.needed_secrets = [NM.SETTING_802_1X_PASSWORD, NM.SETTING_802_1X_PRIVATE_KEY_PASSWORD]
+
+    def make_certs(self):
+        os.mkdir(self.tmpdir)
+
+        with open(f'{self.tmpdir}/hostapd.eap_user', 'w') as f:
+            f.write('''* PEAP,TLS
+
+"account1" MSCHAPV2 "password1" [2]
+"account2" MSCHAPV2 "password2" [2]
+''')
+
+        # Create a CA, server and client certificates protected by passw0rd and the DH parameters
+        create_ca_script = """/usr/share/easy-rsa/easyrsa init-pki
+EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-ca nopass
+EASYRSA_PASSOUT=pass:passw0rd EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-server-full server
+EASYRSA_PASSOUT=pass:passw0rd EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client
+/usr/share/easy-rsa/easyrsa gen-dh
+"""
+
+        with open(f'{self.tmpdir}/make_certs.sh', 'w') as f:
+            f.write(create_ca_script)
+
+        cmd = ['bash', 'make_certs.sh']
+        subprocess.call(cmd, stdout=subprocess.DEVNULL,
+                        stderr=subprocess.DEVNULL, cwd=self.tmpdir)
+
+
+class NetworkTestWifi(base.NetworkTestBase):
+    """Wifi functionality for network test cases
+
+    setUp() creates two test wlan devices, one for a simulated access point
+    (self.dev_w_ap), the other for a simulated client device
+    (self.dev_w_client), and two test ethernet devices (self.dev_e_ap and
+    self.dev_e_client).
+
+    Each test should call self.setup_ap() or self.setup_eth() with the desired
+    configuration.
+    """
+
+    @classmethod
+    def setUpClass(klass):
+        super().setUpClass()
+        klass.SSID = "fake net"
+        # check availability of programs, and cleanly skip test if they are not
+        # available
+        for program in ["wpa_supplicant", "hostapd", "iw"]:
+            if shutil.which(program) is None:
+                raise SystemError("%s is required for this test suite, but not available" % program)
+
+        klass.orig_country = None
+        # ensure we have this so that iw works
+        try:
+            subprocess.check_call(['modprobe', 'cfg80211'])
+            # set regulatory domain "EU", so that we can use 80211.a 5 GHz channels
+            out = subprocess.check_output(['iw', 'reg', 'get'], text=True)
+            m = re.match(r'^(?:global\n)?country (\S+):', out)
+            assert m
+            klass.orig_country = m.group(1)
+            subprocess.check_call(['iw', 'reg', 'set', 'EU'])
+        except Exception:
+            print('cfg80211 (wireless) is unavailable, can\'t test', file=sys.stderr)
+            raise
+
+    @classmethod
+    def tearDownClass(klass):
+        if klass.orig_country is not None:
+            subprocess.check_call(['iw', 'reg', 'set', klass.orig_country])
+        super().tearDownClass()
+
+    @classmethod
+    def create_devices(klass):
+        """Create Access Point and Client devices with mac80211_hwsim and veth"""
+        # TODO: Consider using some trickery, to allow loading modules on the
+        # host by name/alias from within a container.
+        # https://github.com/weaveworks/weave/issues/3115
+        # https://x.com/lucabruno/status/902934379835662336
+        # https://github.com/docker-library/docker/blob/master/modprobe.sh  # wokeignore:rule=master
+        # https://github.com/torvalds/linux/blob/master/net/core/dev_ioctl.c:dev_load()  # wokeignore:rule=master
+        # e.g. via netdev ioctl SIOCGIFINDEX:
+        # https://github.com/weaveworks/go-odp/blob/master/odp/dpif.go#L67  # wokeignore:rule=master
+        #
+        # Or alternatively, port the WiFi testing to virt_wifi, which can be
+        # auto-loaded via "ip link add link eth0 name wlan42 type virt_wifi"
+        # inside a (privileged) LXC container, as used by autopkgtest.
+
+        if os.path.exists("/sys/module/mac80211_hwsim"):
+            raise SystemError("mac80211_hwsim module already loaded")
+        # create virtual wlan devs
+        before_wlan = set([c for c in os.listdir("/sys/class/net") if c.startswith("wlan")])
+        subprocess.check_call(["modprobe", "mac80211_hwsim"])
+        # wait 5 seconds for fake devices to appear
+        timeout = 50
+        while timeout > 0:
+            after_wlan = set([c for c in os.listdir("/sys/class/net") if c.startswith("wlan")])
+            if len(after_wlan) - len(before_wlan) >= 2:
+                break
+            timeout -= 1
+            time.sleep(0.1)
+        else:
+            raise SystemError("timed out waiting for fake devices to appear")
+
+        devs = list(after_wlan - before_wlan)
+        klass.dev_w_ap = devs[0]
+        klass.dev_w_client = devs[1]
+
+        # determine and store MAC addresses
+        # Creation of the veths introduces a race with newer versions of
+        # systemd, as it  will change the initial MAC address after the device
+        # was created and networkd took control. Give it some time, so we read
+        # the correct MAC address
+        time.sleep(1)
+        with open("/sys/class/net/%s/address" % klass.dev_w_ap) as f:
+            klass.mac_w_ap = f.read().strip().upper()
+        with open("/sys/class/net/%s/address" % klass.dev_w_client) as f:
+            klass.mac_w_client = f.read().strip().upper()
+        # print('Created fake devices: AP: %s, client: %s' % (klass.dev_w_ap, klass.dev_w_client))
+        super().create_devices()
+
+    @classmethod
+    def shutdown_devices(klass):
+        """Remove test wlan devices"""
+        super().shutdown_devices()
+        klass.dev_w_ap = None
+        klass.dev_w_client = None
+        subprocess.check_call(["rmmod", "mac80211_hwsim"])
+
+    def setup_ap(self, hostapd_conf, ipv6_mode):
+        """Set up simulated access point
+
+        On self.dev_w_ap, run hostapd with given configuration. Setup dnsmasq
+        according to ipv6_mode, see start_dnsmasq().
+
+        This is torn down automatically at the end of the test.
+        """
+        # give our AP an IP
+        subprocess.check_call(["ip", "a", "flush", "dev", self.dev_w_ap])
+        if ipv6_mode is not None:
+            subprocess.check_call(
+                ["ip", "a", "add", "2600::1/64", "dev", self.dev_w_ap]
+            )
+        else:
+            subprocess.check_call(
+                ["ip", "a", "add", "192.168.5.1/24", "dev", self.dev_w_ap]
+            )
+
+        self.start_hostapd(hostapd_conf)
+        self.start_dnsmasq(ipv6_mode, self.dev_w_ap)
+
+    def start_wpasupp(self, conf):
+        """Start wpa_supplicant on client interface"""
+
+        w_conf = os.path.join(self.workdir, "wpasupplicant.conf")
+        with open(w_conf, "w") as f:
+            f.write("ctrl_interface=%s\nnetwork={\n%s\n}\n" % (self.workdir, conf))
+        log = os.path.join(self.workdir, "wpasupp.log")
+        p = subprocess.Popen(
+            [
+                "wpa_supplicant",
+                "-Dwext",
+                "-i",
+                self.dev_w_client,
+                "-e",
+                self.entropy_file,
+                "-c",
+                w_conf,
+                "-f",
+                log,
+            ],
+            stderr=subprocess.PIPE,
+        )
+        self.addCleanup(p.wait)
+        self.addCleanup(p.terminate)
+        # TODO: why does this sometimes take so long?
+        self.poll_text(log, "CTRL-EVENT-CONNECTED", timeout=200)
+
+    def start_hostapd(self, conf):
+        hostapd_conf = os.path.join(self.workdir, "hostapd.conf")
+        with open(hostapd_conf, "w") as f:
+            f.write("interface=%s\ndriver=nl80211\n" % self.dev_w_ap)
+            f.write(conf)
+
+        log = os.path.join(self.workdir, "hostapd.log")
+        p = subprocess.Popen(
+            ["hostapd", "-e", self.entropy_file, "-f", log, hostapd_conf],
+            stdout=subprocess.PIPE,
+        )
+        self.addCleanup(p.wait)
+        self.addCleanup(p.terminate)
+        self.poll_text(log, "" + self.dev_w_ap + ": AP-ENABLED")
+
+    def wait_ap(self, timeout):
+        """Wait for AccessPoint NM object to appear, and return it"""
+
+        self.assertEventually(
+            lambda: len(self.nmdev_w.get_access_points()) > 0,
+            "timed out waiting for AP to be detected",
+            timeout=timeout,
+        )
+
+        return self.nmdev_w.get_access_points()[0]
+
+    def connect_to_ap(self, ap, auth_settings, ipv6_mode, ip6_privacy):
+        """Connect to an NMAccessPoint.
+
+        auth_settings should be None for open networks and an instance of
+        WifiAuthentication for WEP/WPA-PSK/WPA-EAP.
+
+        ip6_privacy is a NM.SettingIP6ConfigPrivacy flag.
+
+        Return (NMConnection, NMActiveConnection) objects.
+        """
+
+        ip4_method = NM.SETTING_IP4_CONFIG_METHOD_DISABLED
+        ip6_method = NM.SETTING_IP6_CONFIG_METHOD_IGNORE
+        if ipv6_mode is None:
+            ip4_method = NM.SETTING_IP4_CONFIG_METHOD_AUTO
+        else:
+            ip6_method = NM.SETTING_IP6_CONFIG_METHOD_AUTO
+
+        # If we have a secret, supply it to the new connection right away;
+        # adding it afterwards with update_secrets() does not work, and we
+        # can't implement a SecretAgent as get_secrets() would need to build a
+        # map of a map of gpointers to gpointers which is too much for PyGI
+        partial_conn = NM.SimpleConnection.new()
+        partial_conn.add_setting(NM.SettingIP4Config(method=ip4_method))
+        if auth_settings:
+            partial_conn.add_setting(auth_settings.auth_settings)
+            if isinstance(auth_settings, WifiAuthenticationWPAEAP):
+                partial_conn.add_setting(auth_settings.auth_eap_settings)
+        if ip6_privacy is not None:
+            partial_conn.add_setting(
+                NM.SettingIP6Config(ip6_privacy=ip6_privacy, method=ip6_method)
+            )
+
+        ml = GLib.MainLoop()
+        self.cb_conn = None
+        self.cancel = Gio.Cancellable()
+        self.timeout_tag = 0
+
+        def add_activate_cb(client, res, data):
+            if self.timeout_tag > 0:
+                GLib.source_remove(self.timeout_tag)
+                self.timeout_tag = 0
+            try:
+                self.cb_conn = self.nmclient.add_and_activate_connection_finish(res)
+            except gi.repository.GLib.Error as e:
+                # Check if the error is "Operation was cancelled"
+                if e.domain != "g-io-error-quark" or e.code != 19:
+                    self.fail(
+                        "add_and_activate_connection failed: %s (%s, %d)"
+                        % (e.message, e.domain, e.code)
+                    )
+            ml.quit()
+
+        def timeout_cb():
+            self.timeout_tag = -1
+            self.cancel.cancel()
+            ml.quit()
+            return GLib.SOURCE_REMOVE
+
+        self.nmclient.add_and_activate_connection_async(
+            partial_conn,
+            self.nmdev_w,
+            ap.get_path(),
+            self.cancel,
+            add_activate_cb,
+            None,
+        )
+        self.timeout_tag = GLib.timeout_add_seconds(300, timeout_cb)
+        ml.run()
+        if self.timeout_tag < 0:
+            self.timeout_tag = 0
+            self.fail("Main loop for adding connection timed out!")
+        self.assertNotEqual(self.cb_conn, None)
+        active_conn = self.cb_conn
+        self.cb_conn = None
+
+        conn = self.conn_from_active_conn(active_conn)
+        self.assertTrue(conn.verify())
+
+        # verify need_secrets()
+        needed_secrets = conn.need_secrets()
+        if auth_settings is None:
+            self.assertEqual(needed_secrets, (None, []))
+        else:
+            self.assertEqual(
+                needed_secrets[0], auth_settings.setting_name
+            )
+            self.assertEqual(type(needed_secrets[1]), list)
+            self.assertGreaterEqual(len(needed_secrets[1]), 1)
+            self.assertIn(needed_secrets[1][0], auth_settings.needed_secrets)
+
+        # we are usually ACTIVATING at this point; wait for completion
+        # TODO: 5s is not enough, argh slow DHCP client
+        self.assertEventually(
+            lambda: active_conn.get_state() == NM.ActiveConnectionState.ACTIVATED,
+            "timed out waiting for %s to get activated" % active_conn.get_connection(),
+            timeout=600,
+        )
+        self.assertEqual(self.nmdev_w.get_state(), NM.DeviceState.ACTIVATED)
+        return (conn, active_conn)
+
+    # libnm-glib has a lot of internal persistent state (private D-BUS
+    # connections and such); as it is very brittle and hard to track down
+    # all remaining references to any NM* object after a test, we rather
+    # run each test in a separate subprocess
+    @run_in_subprocess
+    def do_test(
+        self,
+        hostapd_conf,
+        ipv6_mode,
+        expected_max_bitrate,
+        auth_settings=None,
+        ip6_privacy=None,
+    ):
+        """Actual test code, parameterized for the particular test case"""
+
+        self.setup_ap(hostapd_conf, ipv6_mode)
+        self.start_nm(self.dev_w_client)
+
+        # on coldplug we expect the AP to be picked out fast
+        ap = self.wait_ap(timeout=100)
+        self.assertTrue(ap.get_path().startswith("/org/freedesktop/NetworkManager"))
+        self.assertEqual(ap.get_mode(), getattr(NM, "80211Mode").INFRA)
+        self.assertEqual(ap.get_max_bitrate(), expected_max_bitrate)
+        # self.assertEqual(ap.get_flags(), )
+
+        # should not auto-connect
+        self.assertEqual(self.filtered_active_connections(), [])
+
+        # connect to that AP
+        (conn, active_conn) = self.connect_to_ap(ap, auth_settings, ipv6_mode, ip6_privacy)
+
+        # check NMActiveConnection object
+        self.assertIn(
+            active_conn.get_uuid(),
+            [c.get_uuid() for c in self.filtered_active_connections()],
+        )
+        self.assertEqual(
+            [d.get_udi() for d in active_conn.get_devices()], [self.nmdev_w.get_udi()]
+        )
+
+        # check corresponding NMConnection object
+        wireless_setting = conn.get_setting_wireless()
+        self.assertEqual(wireless_setting.get_ssid().get_data(), self.SSID.encode())
+        self.assertEqual(wireless_setting.get_hidden(), False)
+        if auth_settings:
+            self.assertEqual(
+                conn.get_setting_wireless_security().get_name(),
+                NM.SETTING_WIRELESS_SECURITY_SETTING_NAME,
+            )
+        else:
+            self.assertEqual(conn.get_setting_wireless_security(), None)
+        # for debugging
+        # conn.dump()
+
+        # for IPv6, check privacy setting
+        if ipv6_mode is not None and ip6_privacy != NM.SettingIP6ConfigPrivacy.UNKNOWN:
+            assert (
+                ip6_privacy is not None
+            ), "for IPv6 tests you need to specify ip6_privacy flag"
+            ip6_setting = conn.get_setting_ip6_config()
+            self.assertEqual(ip6_setting.props.ip6_privacy, ip6_privacy)
+
+        self.check_low_level_config(self.dev_w_client, ipv6_mode, ip6_privacy)
+
+    def start_nm(self, wait_iface=None, auto_connect=True):
+        super().start_nm(wait_iface, auto_connect,
+                       managed_devices = [self.dev_w_client, self.dev_e_client])
+
+        # determine device objects
+        for d in self.nmclient.get_devices():
+            if d.props.interface == self.dev_w_ap:
+                self.assertEqual(d.get_device_type(), NM.DeviceType.WIFI)
+                self.assertEqual(d.get_driver(), "mac80211_hwsim")
+                self.assertEqual(d.get_hw_address(), self.mac_w_ap)
+                self.nmdev_w_ap = d
+            elif d.props.interface == self.dev_w_client:
+                self.assertEqual(d.get_device_type(), NM.DeviceType.WIFI)
+                self.assertEqual(d.get_driver(), "mac80211_hwsim")
+                # NM ≥ 1.4 randomizes MAC addresses by default, so we can't
+                # test for equality, just make sure it's not our AP
+                self.assertNotEqual(d.get_hw_address(), self.mac_w_ap)
+                self.nmdev_w = d
+
+        self.assertTrue(
+            hasattr(self, "nmdev_w_ap"), "Could not determine wifi AP NM device"
+        )
+        self.assertTrue(
+            hasattr(self, "nmdev_w"), "Could not determine wifi client NM device"
+        )
+
+        self.process_glib_events()
+
+    def shutdown_connections(self):
+        super().shutdown_connections()
+        # verify that NM properly deconfigures the WiFi devices
+        try:
+            self.assert_iface_down(self.dev_w_client, False)
+        except AssertionError as e:
+            # Log message is hidden by default, when called from an "addCleanup"
+            # hook. So let's log it explicitly:
+            print(f"AssertionError: {e}")
+            raise
+
+    def assert_iface_down(self, iface, validate_dev_w_ap=True):
+        """Assert that client interface is down"""
+
+        super().assert_iface_down(iface)
+
+        if iface == self.dev_w_client:
+            out = subprocess.check_output(
+                ["iw", "dev", iface, "link"], universal_newlines=True
+            )
+            self.assertIn("Not connected", out)
+
+            # but AP device should never be touched by NM
+            if validate_dev_w_ap:
+                self.assert_iface_up(self.dev_w_ap)
+
+
+    def assert_iface_up(self, iface, expected_ip_a=None, unexpected_ip_a=None):
+        """Assert that client interface is up"""
+
+        super().assert_iface_up(iface, expected_ip_a, unexpected_ip_a)
+
+        if iface == self.dev_w_client:
+            out = subprocess.check_output(
+                ["iw", "dev", iface, "link"], universal_newlines=True
+            )
+            self.assertIn("Connected to " + self.mac_w_ap, out)
+            self.assertIn("SSID: " + self.SSID, out)
+
+    @classmethod
+    def _rfkill_attribute(klass, interface):
+        """Return the path to interface's rfkill soft toggle in sysfs."""
+
+        g = glob("/sys/class/net/%s/phy80211/rfkill*/soft" % interface)
+        assert (
+            len(g) == 1
+        ), 'Did not find exactly one "soft" rfkill attribute for %s: %s' % (
+            interface,
+            str(g),
+        )
+        return g[0]
+
+    @classmethod
+    def get_rfkill(klass, interface):
+        """Get rfkill status of an interface.
+
+        Returns whether the interface is blocked, i. e. "True" for blocked,
+        "False" for enabled.
+        """
+        with open(klass._rfkill_attribute(interface)) as f:
+            val = f.read()
+        return val == "1"
+
+    @classmethod
+    def set_rfkill(klass, interface, block):
+        """Set rfkill status of an interface
+
+        Use block==True for disabling ("killswitching") an interface,
+        block==False to re-enable.
+        """
+        with open(klass._rfkill_attribute(interface), "w") as f:
+            f.write(block and "1" or "0")
diff -pruN 1.52.0-1/debian/tests/control 1.52.0-1ubuntu1/debian/tests/control
--- 1.52.0-1/debian/tests/control	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/control	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,29 @@
+Features: test-name=nm-eth.py
+Tests-Directory: debian/tests
+Test-Command: ./debian/tests/prep-testbed.sh && python3 debian/tests/nm-eth.py
+Depends: python3, udev, dnsmasq-base, gir1.2-nm-1.0, network-manager, python3-dbusmock
+Restrictions: needs-root, allow-stderr, isolation-container, breaks-testbed
+
+Features: test-name=wpa-dhcp.py
+Tests-Directory: debian/tests
+Test-Command: (modprobe cfg80211 || exit 77) && (modprobe mac80211_hwsim || exit 77) && rmmod mac80211_hwsim && python3 debian/tests/wpa-dhcp.py
+Depends: python3, hostapd, dnsmasq-base, gir1.2-nm-1.0, wpasupplicant, dhcpcd-base, iw
+Restrictions: needs-root allow-stderr isolation-container skippable
+
+Features: test-name=nm-wifi.py
+Tests-Directory: debian/tests
+Test-Command: (modprobe cfg80211 || exit 77) && (modprobe mac80211_hwsim || exit 77) && rmmod mac80211_hwsim && python3 debian/tests/nm-wifi.py
+Depends: python3, dnsmasq-base, gir1.2-nm-1.0, network-manager, hostapd, iw, python3-dbusmock, python3-netaddr, wpasupplicant, easy-rsa
+Restrictions: needs-root isolation-container skippable
+
+Tests: killswitches-no-urfkill
+Depends: network-manager, build-essential, linux-headers-generic [!i386], rfkill
+Restrictions: needs-root allow-stderr isolation-machine skippable
+
+Tests: urfkill-integration
+Depends: network-manager, build-essential, linux-headers-generic [!i386], rfkill, urfkill, polkitd
+Restrictions: needs-root allow-stderr isolation-machine skippable
+
+Tests: nm-netplan.py
+Depends: python3, gir1.2-nm-1.0, network-manager, netplan.io, openvpn, easy-rsa, network-manager-openvpn, dnsmasq-base, hostapd, wpasupplicant, ubuntu-settings, python3-gi
+Restrictions: needs-root allow-stderr isolation-container
diff -pruN 1.52.0-1/debian/tests/fake-rfkill.c 1.52.0-1ubuntu1/debian/tests/fake-rfkill.c
--- 1.52.0-1/debian/tests/fake-rfkill.c	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/fake-rfkill.c	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,51 @@
+#include <linux/rfkill.h>
+#include <linux/module.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+
+static struct rfkill *rfk;
+
+static void test_poll(struct rfkill *rfkill, void *data)
+{
+	printk(KERN_DEBUG "poll test rfkill\n");
+}
+
+static void test_query(struct rfkill *rfkill, void *data)
+{
+	printk(KERN_DEBUG "query test rfkill\n");
+}
+
+static int test_set_block(void *data, bool blocked)
+{
+	printk(KERN_DEBUG "set test rfkill (%s)\n",
+		blocked ? "blocked" : "active");
+	return 0;
+}
+
+static struct rfkill_ops ops = {
+	.poll = test_poll,
+	.query = test_query,
+	.set_block = test_set_block,
+};
+
+int mod_init(void)
+{
+	int err;
+
+	rfk = rfkill_alloc("fake", NULL, RFKILL_TYPE_WLAN, &ops, NULL);
+	if (!rfk)
+		return -ENOMEM;
+	err = rfkill_register(rfk);
+	if (err)
+		rfkill_destroy(rfk);
+	return err;
+}
+module_init(mod_init);
+
+void mod_exit(void)
+{
+	rfkill_unregister(rfk);
+	rfkill_destroy(rfk);
+}
+module_exit(mod_exit);
diff -pruN 1.52.0-1/debian/tests/killswitches-no-urfkill 1.52.0-1ubuntu1/debian/tests/killswitches-no-urfkill
--- 1.52.0-1/debian/tests/killswitches-no-urfkill	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/killswitches-no-urfkill	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+if dpkg --print-architecture | grep s390; then
+    echo "Skipping rfkill tests on s390 (LP: #1855009)"
+    exit 77
+fi
+
+if dpkg --print-architecture | grep i386; then
+    echo "Skipping rfkill tests on i386 (LP: #1855183)"
+    exit 77
+fi
+
+set -e
+
+make -f debian/tests/Makefile fake-rfkill
+# poor man's dependency resolver
+DEPS=$(modinfo debian/tests/fake-rfkill.ko | sed -n '/depends:/ {s/^.*://; s/[[:space:]]*$//; p}')
+[ -z "$DEPS" ] || modprobe "$DEPS"
+insmod debian/tests/fake-rfkill.ko
+
+fake_id=$(rfkill list | grep fake | awk -F: '{ print $1; }')
+
+service NetworkManager start
+sleep 30
+
+# test blocking the device
+rfkill block $fake_id
+if ! rfkill list $fake_id | grep 'Soft' | awk '{ print $3; }' | grep -qc yes; then
+	echo "ERROR: could not block fake device"
+	rmmod fake-rfkill || true
+	exit 1
+fi
+
+# The systemd-rfkill service starts up whenever rfkill changes state, so on a
+# 1-cpu system that might delay the event change from reaching nm before the
+# check below, causing this test to fail.  The settle added here delays the
+# nmcli check until after the rfkill uevent has definitely been processed.
+udevadm settle
+
+if ! LC_MESSAGES=C nmcli radio wifi | grep -qc disabled; then
+	echo "ERROR: NM could not track device state."
+	rmmod fake-rfkill || true
+	exit 1
+fi
+
+# test unblocking the device
+rfkill unblock $fake_id
+if ! rfkill list $fake_id | grep 'Soft' | awk '{ print $3; }' | grep -qc no; then
+	echo "ERROR: could not unblock fake device"
+	rmmod fake-rfkill || true
+	exit 1
+fi
+
+# same reason as above, however since systemd-rfkill stays running for 30 secs or so
+# it's unlikely that it would start up again here, but it's still safer to call settle
+udevadm settle
+
+if ! LC_MESSAGES=C nmcli radio wifi | grep -qc enabled; then
+	echo "ERROR: NM could not track device state to enabled."
+	rmmod fake-rfkill || true
+	exit 1
+fi
+
+rmmod fake-rfkill
+make -f debian/tests/Makefile clean-rfkill
+
+echo OK
diff -pruN 1.52.0-1/debian/tests/nm-eth.py 1.52.0-1ubuntu1/debian/tests/nm-eth.py
--- 1.52.0-1/debian/tests/nm-eth.py	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/nm-eth.py	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,130 @@
+#!/usr/bin/env python3
+# Test NetworkManager on simulated network devices
+# For an interactive shell, run "nm-eth.py ColdplugEthernet.shell", see below.
+
+__author__ = "Martin Pitt <martin.pitt@ubuntu.com>"
+__copyright__ = "(C) 2013-2025 Canonical Ltd."
+__license__ = "GPL v2 or later"
+
+import os
+import os.path
+import subprocess
+import sys
+import unittest
+
+import gi
+
+import base
+
+gi.require_version("NM", "1.0")
+from gi.repository import NM
+
+
+class ColdplugEthernet(base.NetworkTestBase):
+    """Ethernet: In these tests NM starts after setting up the router"""
+
+    # not run by default; run "nm-eth.py ColdplugEthernet.shell" to get this
+    @base.run_in_subprocess
+    def shell(self):
+        """Start router and NM, then run a shell (for debugging)"""
+
+        self.setup_eth(None)
+        self.start_nm(self.dev_e_client)
+        print(
+            """
+
+client interface: %s, router interface: %s
+
+You can now run commands like "nmcli dev".
+Logs are in '%s'. When done, exit the shell.
+
+"""
+            % (self.dev_e_client, self.dev_e_ap, self.workdir)
+        )
+        subprocess.call(["bash", "-i"])
+
+    def test_auto_ip4(self):
+        """ethernet: auto-connection, IPv4"""
+
+        self.do_test(None, auto_connect=True)
+
+    def test_auto_ip6_raonly_no_pe(self):
+        """ethernet: auto-connection, IPv6 with only RA, PE disabled"""
+
+        self.do_test(
+            "ra-only",
+            auto_connect=True,
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.DISABLED,
+        )
+
+    def test_auto_ip6_dhcp(self):
+        """ethernet: auto-connection, IPv6 with DHCP"""
+
+        self.do_test(
+            "", auto_connect=True, ip6_privacy=NM.SettingIP6ConfigPrivacy.UNKNOWN
+        )
+
+    def test_manual_ip4(self):
+        """ethernet: manual connection, IPv4"""
+
+        self.do_test(None, auto_connect=False)
+
+    def test_manual_ip6_raonly_tmpaddr(self):
+        """ethernet: manual connection, IPv6 with only RA, preferring temp address"""
+
+        self.do_test(
+            "ra-only",
+            auto_connect=False,
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_TEMP_ADDR,
+        )
+
+    def test_manual_ip6_raonly_pubaddr(self):
+        """ethernet: manual connection, IPv6 with only RA, preferring public address"""
+
+        self.do_test(
+            "ra-only",
+            auto_connect=False,
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_PUBLIC_ADDR,
+        )
+
+
+class HotplugEthernet(base.NetworkTestBase):
+    """In these tests routers are are created while NM is already running"""
+
+    @base.run_in_subprocess
+    def test_auto_detect_eth(self):
+        """new eth router is being detected automatically within 30s"""
+
+        self.start_nm()
+        self.setup_eth(None)
+        self.assertEventually(
+            lambda: len(self.filtered_active_connections()) > 0, timeout=300
+        )
+        active_conn = self.filtered_active_connections()[0]
+
+        self.assertEventually(
+            lambda: active_conn.get_state() == NM.ActiveConnectionState.ACTIVATED,
+            "timed out waiting for %s to get activated" % active_conn.get_connection(),
+            timeout=80,
+        )
+        self.assertEqual(self.nmdev_e.get_state(), NM.DeviceState.ACTIVATED)
+
+        conn = self.conn_from_active_conn(active_conn)
+        self.assertTrue(conn.verify())
+
+
+def setUpModule():
+    base.set_up_module()
+
+def tearDownModule():
+    base.tear_down_module()
+
+
+if __name__ == "__main__":
+    # avoid unintelligible error messages when not being root
+    if os.getuid() != 0:
+        raise SystemExit("This integration test suite needs to be run as root")
+
+    # write to stdout, not stderr
+    runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)
+    unittest.main(testRunner=runner)
diff -pruN 1.52.0-1/debian/tests/nm-netplan.py 1.52.0-1ubuntu1/debian/tests/nm-netplan.py
--- 1.52.0-1/debian/tests/nm-netplan.py	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/nm-netplan.py	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,870 @@
+#!/usr/bin/python3
+
+__author__ = "Danilo Egea Gondolfo <danilo.egea.gondolfo@canonical.com>"
+__copyright__ = "(C) 2023 Canonical Ltd."
+__license__ = "GPL v2 or later"
+
+from glob import glob
+import json
+import shutil
+import socket
+import subprocess
+import sys
+import os
+from time import sleep
+import unittest
+import yaml
+
+import gi
+gi.require_version("NM", "1.0")
+from gi.repository import NM, GLib, Gio
+
+import base_wifi
+
+nmclient = NM.Client.new()
+
+class TestNetplan(unittest.TestCase):
+
+    def setUp(self):
+        self._stop_network_manager()
+
+        self._start_nm()
+        sleep(1)
+        self.nmclient = NM.Client.new()
+
+    def tearDown(self):
+        pass
+
+    def _start_nm(self, auto_connect=True):
+        """This method is basically a copy of start_nm() from nm.py
+        without the parts we don't need
+        """
+
+        if not os.path.exists("/run/NetworkManager"):
+            os.mkdir("/run/NetworkManager")
+        for d in [
+            "/etc/NetworkManager",
+            "/var/lib/NetworkManager",
+            "/run/NetworkManager",
+            "/etc/netplan",
+        ]:
+            subprocess.check_call(["mount", "-n", "-t", "tmpfs", "none", d])
+            self.addCleanup(subprocess.call, ["umount", d])
+        os.mkdir("/etc/NetworkManager/system-connections")
+
+        denylist = ""
+        for iface in os.listdir("/sys/class/net"):
+            if iface in ['bonding_masters']:
+                continue
+            with open("/sys/class/net/%s/address" % iface) as f:
+                if denylist:
+                    denylist += ";"
+                denylist += "mac:%s" % f.read().strip()
+
+        conf = "/etc/NetworkManager/NetworkManager.conf"
+        extra_main = ""
+        if not auto_connect:
+            extra_main += "no-auto-default=*\n"
+
+        with open(conf, "w") as f:
+            f.write(
+                "[main]\nplugins=keyfile\n%s\n[keyfile]\nunmanaged-devices=%s\n"
+                % (extra_main, denylist)
+            )
+
+        # We start NM via systemd because its .service file sets some restrictions
+        # at run time, such as ProtectSystem and ProtectHome, and we want to test it
+        # with these restrictions in place.
+        # Sleep for 5 seconds to prevent hitting "start-limit-hit" in systemd.
+        sleep(5)
+        self._start_network_manager()
+        base_wifi.wait_nm_online()
+        # automatically terminate process at end of test case
+        self.addCleanup(self._stop_network_manager)
+        self.addCleanup(self._clear_connections)
+
+        self._process_glib_events()
+
+    def _process_glib_events(self):
+        """Process pending GLib main loop events"""
+
+        context = GLib.MainContext.default()
+        while context.iteration(False):
+            pass
+
+    def _start_network_manager(self):
+        cmd = ['systemctl', 'start', 'NetworkManager']
+        subprocess.call(cmd, stdout=subprocess.DEVNULL)
+
+    def _restart_network_manager(self):
+        cmd = ['systemctl', 'restart', 'NetworkManager']
+        subprocess.call(cmd, stdout=subprocess.DEVNULL)
+
+    def _stop_network_manager(self):
+        cmd = ['systemctl', 'stop', 'NetworkManager']
+        subprocess.call(cmd, stdout=subprocess.DEVNULL)
+
+    def _add_connection(self, connection):
+        self.main_loop = GLib.MainLoop()
+        self.cancel = Gio.Cancellable()
+        self.timeout_tag = 0
+
+        def add_cb(client, result, data):
+            self.nmclient.add_connection_finish(result)
+            self.main_loop.quit()
+
+        def timeout_cb():
+            self.timeout_tag = -1
+            self.cancel.cancel()
+            self.main_loop.quit()
+            return GLib.SOURCE_REMOVE
+
+        self.timeout_tag = GLib.timeout_add_seconds(120, timeout_cb)
+
+        self.nmclient.add_connection_async(connection, True, self.cancel, add_cb, None)
+        self.main_loop.run()
+
+        if self.timeout_tag < 0:
+            self.timeout_tag = 0
+            self.fail('nm_netplan.py: main loop timed out during connection creation')
+
+
+    def _delete_connection(self, connection):
+        uuid = connection.get_uuid()
+        cmd = ['nmcli', 'con', 'del', uuid]
+        subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+    def _delete_interface(self, connection):
+        iface = connection.get_interface_name()
+        if iface:
+            cmd = ['ip', 'link', 'del', iface]
+            subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+    def _nmcli(self, parameters):
+        cmd = ['nmcli'] + parameters
+        return subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+    def _bridge_show(self, bridge):
+        cmd = ['bridge', '-j', 'link', 'show', bridge]
+        ret = subprocess.run(cmd, capture_output=True)
+        return json.loads(ret.stdout)
+
+    def _load_netplan_yaml_for_connection(self, connection):
+        filename = '/etc/netplan/90-NM-' + connection.get_uuid() + '.yaml'
+
+        file = open(filename)
+        data = yaml.safe_load(file)
+        file.close()
+        return data
+
+    def _get_number_of_yaml_files(self):
+        return len(self._get_list_of_yaml_files())
+
+    def _get_list_of_yaml_files(self):
+        return glob("/etc/netplan/90-NM-*")
+
+    def _commit_and_save_connection(self, connection):
+        main_loop = GLib.MainLoop()
+
+        def commit_cb(client, result, data):
+            connection.commit_changes_finish(result)
+            main_loop.quit()
+
+        connection.commit_changes_async(True, None, commit_cb, None)
+        main_loop.run()
+
+    def _clear_connections(self):
+        for conn in self.nmclient.get_connections():
+            self._delete_connection(conn)
+            self._delete_interface(conn)
+
+    def _netplan_generate(self):
+        cmd = ['netplan', 'generate']
+        ret = subprocess.run(cmd, capture_output=True)
+
+    def _nmcli_con_reload(self):
+        self._nmcli(['con', 'reload'])
+
+    # Tests
+
+    def test_create_a_simple_bridge_with_dhcp(self):
+
+        conn = NM.SimpleConnection.new()
+        settings = NM.SettingConnection.new()
+        settings.set_property(NM.SETTING_CONNECTION_ID, "bridge0")
+        settings.set_property(NM.SETTING_CONNECTION_INTERFACE_NAME, "bridge0")
+        settings.set_property(NM.SETTING_CONNECTION_TYPE, "bridge")
+
+        bridge = NM.SettingBridge.new()
+        ipv4 = NM.SettingIP4Config.new()
+        ipv4.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto")
+        ipv6 = NM.SettingIP6Config.new()
+        ipv6.set_property(NM.SETTING_IP_CONFIG_METHOD, "auto")
+
+        conn.add_setting(settings)
+        conn.add_setting(ipv4)
+        conn.add_setting(ipv6)
+        conn.add_setting(bridge)
+
+        # There should be zero netplan NM yaml before adding a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+        self._add_connection(conn)
+
+        # There should be one netplan NM yaml after adding a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        connection = self.nmclient.get_connection_by_id("bridge0")
+        yaml_data = self._load_netplan_yaml_for_connection(connection)
+
+        # Validating some of the expected flags
+        self.assertTrue(yaml_data['network']['bridges']['bridge0']['dhcp4'])
+        self.assertTrue(yaml_data['network']['bridges']['bridge0']['dhcp6'])
+
+        self._delete_connection(connection)
+
+        # There should be zero netplan NM yaml after deleting a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_create_a_simple_bridge_with_ip_addresses(self):
+        conn = NM.SimpleConnection.new()
+        settings = NM.SettingConnection.new()
+        settings.set_property(NM.SETTING_CONNECTION_ID, "bridge0")
+        settings.set_property(NM.SETTING_CONNECTION_INTERFACE_NAME, "bridge0")
+        settings.set_property(NM.SETTING_CONNECTION_TYPE, "bridge")
+
+        bridge = NM.SettingBridge.new()
+
+        ipv4 = NM.SettingIP4Config.new()
+        ipv4.set_property(NM.SETTING_IP_CONFIG_METHOD, "manual")
+        ip4_addr1 = NM.IPAddress.new(socket.AF_INET, "10.20.30.40", 24)
+        ip4_addr2 = NM.IPAddress.new(socket.AF_INET, "10.20.30.41", 24)
+        ipv4.add_address(ip4_addr1)
+        ipv4.add_address(ip4_addr2)
+
+        ipv6 = NM.SettingIP6Config.new()
+        ipv6.set_property(NM.SETTING_IP_CONFIG_METHOD, "manual")
+        ip6_addr1 = NM.IPAddress.new(socket.AF_INET6, "dead:beef::1", 64)
+        ip6_addr2 = NM.IPAddress.new(socket.AF_INET6, "dead:beef::2", 64)
+        ipv6.add_address(ip6_addr1)
+        ipv6.add_address(ip6_addr2)
+
+        conn.add_setting(settings)
+        conn.add_setting(ipv4)
+        conn.add_setting(ipv6)
+        conn.add_setting(bridge)
+
+        # There should be zero netplan NM yaml before adding a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+        self._add_connection(conn)
+
+        # There should be one netplan NM yaml after adding a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        connection = self.nmclient.get_connection_by_id("bridge0")
+        yaml_data = self._load_netplan_yaml_for_connection(connection)
+
+        # Validating some of the expected flags
+        self.assertNotIn('dhcp4', yaml_data['network']['bridges']['bridge0'])
+        self.assertNotIn('dhcp6', yaml_data['network']['bridges']['bridge0'])
+
+        addresses = yaml_data['network']['bridges']['bridge0']['addresses']
+        expected_addresses = ['10.20.30.40/24', '10.20.30.41/24', 'dead:beef::1/64', 'dead:beef::2/64']
+
+        self.assertListEqual(addresses, expected_addresses)
+
+        self._delete_connection(connection)
+
+        # There should be zero netplan NM yaml after deleting a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_create_a_simple_bridge_with_ip_and_member(self):
+
+        conn = NM.SimpleConnection.new()
+        settings = NM.SettingConnection.new()
+        settings.set_property(NM.SETTING_CONNECTION_ID, "bridge0")
+        settings.set_property(NM.SETTING_CONNECTION_INTERFACE_NAME, "bridge0")
+        settings.set_property(NM.SETTING_CONNECTION_TYPE, "bridge")
+
+        bridge = NM.SettingBridge.new()
+
+        ipv4 = NM.SettingIP4Config.new()
+        ipv4.set_property(NM.SETTING_IP_CONFIG_METHOD, "manual")
+        ip4_addr1 = NM.IPAddress.new(socket.AF_INET, "10.20.30.40", 24)
+        ip4_addr2 = NM.IPAddress.new(socket.AF_INET, "10.20.30.41", 24)
+        ipv4.add_address(ip4_addr1)
+        ipv4.add_address(ip4_addr2)
+
+        ipv6 = NM.SettingIP6Config.new()
+        ipv6.set_property(NM.SETTING_IP_CONFIG_METHOD, "manual")
+        ip6_addr1 = NM.IPAddress.new(socket.AF_INET6, "dead:beef::1", 64)
+        ip6_addr2 = NM.IPAddress.new(socket.AF_INET6, "dead:beef::2", 64)
+        ipv6.add_address(ip6_addr1)
+        ipv6.add_address(ip6_addr2)
+
+        conn.add_setting(settings)
+        conn.add_setting(ipv4)
+        conn.add_setting(ipv6)
+        conn.add_setting(bridge)
+
+        # There should be zero netplan NM yaml before adding a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+        # Adding the bridge
+        self._add_connection(conn)
+
+        # There should be one netplan NM yaml after adding a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        # Creating a tap0 device to be a bridge member
+        tap0 = NM.SimpleConnection.new()
+        tap0_conn_settings = NM.SettingConnection.new()
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_ID, "tap0")
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_INTERFACE_NAME, "tap0")
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_TYPE, "tun")
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_SLAVE_TYPE, "bridge")
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_MASTER, "bridge0")
+
+        tap0_settings = NM.SettingTun.new()
+        tap0_settings.set_property(NM.SETTING_TUN_MODE, NM.SettingTunMode.TAP)
+
+        tap0.add_setting(tap0_conn_settings)
+        tap0.add_setting(tap0_settings)
+        self._add_connection(tap0)
+
+        # There should be two netplan NM yaml after adding the tap
+        self.assertEqual(self._get_number_of_yaml_files(), 2)
+
+        bridge0_connection = self.nmclient.get_connection_by_id("bridge0")
+        yaml_data = self._load_netplan_yaml_for_connection(bridge0_connection)
+
+        # Validating some of the bridge expected flags
+        addresses = yaml_data['network']['bridges']['bridge0']['addresses']
+        expected_addresses = ['10.20.30.40/24', '10.20.30.41/24', 'dead:beef::1/64', 'dead:beef::2/64']
+
+        self.assertListEqual(addresses, expected_addresses)
+
+        # Validating if tap0 is attached to the bridge
+        # It might take a while for the new interface be created...
+        limit = 10
+        while (show_bridge := self._bridge_show('bridge0')) == [] and limit > 0:
+            sleep(1)
+            limit = limit - 1
+        self.assertEqual(show_bridge[0]['master'], 'bridge0')
+        self.assertEqual(show_bridge[0]['ifname'], 'tap0')
+
+        tap0_connection = self.nmclient.get_connection_by_id("tap0")
+        tap_yaml = self._load_netplan_yaml_for_connection(tap0_connection)
+
+        tap0_uuid = tap0_connection.get_uuid()
+        # Validating that the bridge information is in the tap yaml
+        self.assertEqual(tap_yaml['network']['nm-devices']['NM-' + tap0_uuid]['networkmanager']['passthrough']['connection.controller'], 'bridge0')
+
+        self._delete_connection(tap0_connection)
+        # There should be one netplan NM yaml after deleting the tap
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        self._delete_connection(bridge0_connection)
+        # There should be zero netplan NM yaml after deleting the bridge
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_create_an_interface_and_change_it(self):
+        """Add a tap interface and change it after create adding IP addresses to it."""
+
+        # Creating a tap0 device to be a bridge member
+        tap0 = NM.SimpleConnection.new()
+        tap0_conn_settings = NM.SettingConnection.new()
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_ID, "tap0")
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_INTERFACE_NAME, "tap0")
+        tap0_conn_settings.set_property(NM.SETTING_CONNECTION_TYPE, "tun")
+
+        tap0_settings = NM.SettingTun.new()
+        tap0_settings.set_property(NM.SETTING_TUN_MODE, NM.SettingTunMode.TAP)
+
+        tap0.add_setting(tap0_conn_settings)
+        tap0.add_setting(tap0_settings)
+        self._add_connection(tap0)
+
+        # There should be one netplan NM yaml after adding a connection
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        tap0_connection = self.nmclient.get_connection_by_id("tap0")
+
+        ipv4_settings = tap0_connection.get_setting_ip4_config()
+        ipv4_settings.set_property(NM.SETTING_IP_CONFIG_METHOD, "manual")
+        ip4_addr1 = NM.IPAddress.new(socket.AF_INET, "10.20.30.40", 24)
+        ip4_addr2 = NM.IPAddress.new(socket.AF_INET, "10.20.30.41", 24)
+        ipv4_settings.add_address(ip4_addr1)
+        ipv4_settings.add_address(ip4_addr2)
+
+        ipv6_settings = tap0_connection.get_setting_ip6_config()
+        ipv6_settings.set_property(NM.SETTING_IP_CONFIG_METHOD, "manual")
+        ip6_addr1 = NM.IPAddress.new(socket.AF_INET6, "dead:beef::1", 64)
+        ip6_addr2 = NM.IPAddress.new(socket.AF_INET6, "dead:beef::2", 64)
+        ipv6_settings.add_address(ip6_addr1)
+        ipv6_settings.add_address(ip6_addr2)
+
+        self._commit_and_save_connection(tap0_connection)
+
+        # There should be one netplan NM yaml files after chaging the only existing connection
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        self._delete_connection(tap0_connection)
+
+        # There should be zero netplan NM yaml files after removing the only existing connection
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_nmcli_add_device_and_change_it(self):
+        """Uses the nmcli to add a connection and validates if the
+        Netplan YAML file has the expected configuration.
+        It also changes the configuration changing the ipv4 method from auto
+        to manual and adding an IP address. After the change the Netplan YAML
+        file should have the same name.
+        """
+
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+        nmcli_add = ['con', 'add', 'type', 'tun', 'mode', 'tap', 'ifname', 'tap0', 'ipv4.method', 'auto']
+        self._nmcli(nmcli_add)
+
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        files_before = self._get_list_of_yaml_files()
+
+        # After OOB changes, the client must be refreshed apparently
+        self.nmclient = NM.Client.new()
+
+        conn = self.nmclient.get_connection_by_id("tun-tap0")
+        uuid = conn.get_uuid()
+        data = self._load_netplan_yaml_for_connection(conn)
+
+        ip4_method = data.get('network') \
+                         .get('nm-devices') \
+                         .get('NM-' + uuid) \
+                         .get('networkmanager') \
+                         .get('passthrough') \
+                         .get('ipv4.method')
+
+        self.assertEqual(ip4_method, 'auto')
+
+        nmcli_mod = ['con', 'mod', 'tun-tap0', 'ipv4.method', 'manual', 'ipv4.addresses', '10.20.30.40/24']
+        self._nmcli(nmcli_mod)
+
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        files_after = self._get_list_of_yaml_files()
+
+        self.assertListEqual(files_before, files_after)
+
+        data = self._load_netplan_yaml_for_connection(conn)
+
+        ip4_method = data.get('network') \
+                         .get('nm-devices') \
+                         .get('NM-' + uuid) \
+                         .get('networkmanager') \
+                         .get('passthrough') \
+                         .get('ipv4.method')
+
+        ip4_addr = data.get('network') \
+                         .get('nm-devices') \
+                         .get('NM-' + uuid) \
+                         .get('networkmanager') \
+                         .get('passthrough') \
+                         .get('ipv4.address1')
+
+        self.assertEqual(ip4_method, 'manual')
+        self.assertEqual(ip4_addr, '10.20.30.40/24')
+
+        self._delete_connection(conn)
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_nmcli_add_wifi_connection(self):
+        """Create a wifi connection via nmcli and check if the expected
+        fields were added to the netplan yaml file."""
+
+        ssid = 'My network SSID'
+        passwd = 'secretpasswd'
+        method = 'wpa-psk'
+        ip = '10.20.30.40/24'
+        nmcli_add = ['con', 'add', 'type', 'wifi', 'ssid', ssid,
+                     'wifi-sec.key-mgmt', method, 'wifi-sec.psk', passwd,
+                     'ipv4.method', 'manual', 'ipv4.addresses', ip]
+
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+        self._nmcli(nmcli_add)
+
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+
+        # After OOB changes, the client must be refreshed apparently
+        self.nmclient = NM.Client.new()
+
+        conn = self.nmclient.get_connection_by_id("wifi")
+        uuid = conn.get_uuid()
+        data = self._load_netplan_yaml_for_connection(conn)
+
+        ap_name = list(data.get('network') \
+                .get('wifis') \
+                .get('NM-' + uuid) \
+                .get('access-points') \
+                .keys())[0]
+
+        ip_addr = data.get('network') \
+                .get('wifis') \
+                .get('NM-' + uuid) \
+                .get('addresses')
+
+        auth_method = data.get('network') \
+                .get('wifis') \
+                .get('NM-' + uuid) \
+                .get('access-points') \
+                .get(ap_name) \
+                .get('auth') \
+                .get('key-management')
+
+        auth_passwd = data.get('network') \
+                .get('wifis') \
+                .get('NM-' + uuid) \
+                .get('access-points') \
+                .get(ap_name) \
+                .get('auth') \
+                .get('password')
+
+        self.assertEqual(ap_name, ssid)
+        self.assertListEqual(ip_addr, [ip])
+        self.assertEqual(auth_method, 'psk')
+        self.assertEqual(auth_passwd, passwd)
+
+        self._delete_connection(conn)
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_create_connection_via_netplan(self):
+        """
+        Create a connection via netplan generate and check if NM will pick it up
+        """
+
+        netplan_yaml = '''network:
+  renderer: NetworkManager
+  ethernets:
+    eth123:
+      dhcp4: true'''
+
+        netplan_yaml_path = '/etc/netplan/10-test.yaml'
+        with open(netplan_yaml_path, 'w') as f:
+            f.write(netplan_yaml)
+        os.chmod(netplan_yaml_path, mode=0o600)
+
+        self._netplan_generate()
+        self._nmcli_con_reload()
+        self.nmclient = NM.Client.new()
+
+        expected = None
+        for conn in self.nmclient.get_connections():
+            if conn.get_id() == 'netplan-eth123':
+                expected = conn
+
+        self.assertIsNotNone(expected)
+
+    def test_create_connection_via_netplan_and_remove_via_nmcli(self):
+        """
+        Create a connection via netplan generate and remove it with nmcli.
+
+        The interface should be removed from the yaml file.
+        """
+
+        netplan_yaml = '''network:
+  renderer: NetworkManager
+  ethernets:
+    eth123:
+      dhcp4: true
+    eth456:
+      dhcp4: true'''
+
+        netplan_yaml_path = '/etc/netplan/10-test.yaml'
+        with open(netplan_yaml_path, 'w') as f:
+            f.write(netplan_yaml)
+        os.chmod(netplan_yaml_path, mode=0o600)
+
+        self._netplan_generate()
+        self._nmcli_con_reload()
+        self.nmclient = NM.Client.new()
+
+        expected1 = None
+        expected2 = None
+        for conn in self.nmclient.get_connections():
+            if conn.get_id() == 'netplan-eth123':
+                expected1 = conn
+            if conn.get_id() == 'netplan-eth456':
+                expected2 = conn
+
+        self.assertIsNotNone(expected1)
+        self.assertIsNotNone(expected1)
+
+        self._delete_connection(expected1)
+
+        with open('/etc/netplan/10-test.yaml', 'r') as f:
+            yaml_data = yaml.safe_load(f)
+
+            # eth123 shouldn't exist anymore
+            self.assertIsNone(yaml_data.get('network').get('ethernets').get('eth123'))
+
+            self.assertIsNotNone(yaml_data.get('network').get('ethernets').get('eth456'))
+
+    def test_create_connection_via_netplan_and_change_it_via_nmcli(self):
+        """
+        Create a connection via netplan generate and change it via nmcli.
+        """
+
+        netplan_yaml = '''network:
+  renderer: NetworkManager
+  ethernets:
+    eth123:
+      dhcp4: false
+      dhcp6: false
+    eth456:
+      dhcp4: true'''
+
+        netplan_yaml_path = '/etc/netplan/10-test.yaml'
+        with open(netplan_yaml_path, 'w') as f:
+            f.write(netplan_yaml)
+        os.chmod(netplan_yaml_path, mode=0o600)
+
+        self._netplan_generate()
+        self._nmcli_con_reload()
+        self._nmcli(['con', 'mod', 'netplan-eth123', 'ipv4.method', 'auto'])
+
+        # eth123.dhcp4 should be overriden by 90-NM-<UUID>.yaml (from 10-test.yaml)
+        # The output of 'netplan get' should account for that.
+        out = subprocess.check_output(['netplan', 'get'], universal_newlines=True)
+        yaml_data = yaml.safe_load(out)
+        dhcp = yaml_data.get('network').get('ethernets').get('eth123').get('dhcp4')
+        self.assertTrue(dhcp)
+
+    def test_openvpn_connection(self):
+        """ Test case for LP#1998207"""
+
+        server_config = """dev tun
+ca /tmp/openvpn/pki/ca.crt
+cert /tmp/openvpn/pki/issued/server.crt
+key /tmp/openvpn/pki/private/server.key
+dh /tmp/openvpn/pki/dh.pem
+server 192.168.5.0 255.255.255.0
+keepalive 10 120
+cipher AES-256-GCM
+compress lz4-v2
+push "compress lz4-v2"
+user root
+log /tmp/openvpn.log
+group root
+"""
+
+        client_config = """client
+dev tun
+remote 127.0.0.1 1194
+nobind
+ca /tmp/openvpn/pki/ca.crt
+cert /tmp/openvpn/pki/issued/client.crt
+key /tmp/openvpn/pki/private/client.key
+cipher AES-256-GCM
+"""
+
+        # The minimum DH size accepted by OpenVPN these days is 2048.
+        # It might take a while to be generated (like almost a minute)
+        # It would be faster to use shared keys instead of TLS but it
+        # seems it's not an option anymore in OpenVPN
+        openvpn_spinup_script = """/usr/share/easy-rsa/easyrsa init-pki
+EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-ca nopass
+EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-server-full server nopass
+EASYRSA_BATCH=1 /usr/share/easy-rsa/easyrsa build-client-full client nopass
+/usr/share/easy-rsa/easyrsa gen-dh
+"""
+
+        tmpdir = '/tmp/openvpn'
+        self.addCleanup(shutil.rmtree, tmpdir)
+        os.mkdir(tmpdir)
+        os.chdir(tmpdir)
+
+        with open('openvpn_spinup.sh', 'w') as f:
+            f.write(openvpn_spinup_script)
+
+        with open('server.conf', 'w') as f:
+            f.write(server_config)
+
+        with open('client.conf', 'w') as f:
+            f.write(client_config)
+
+        cmd = ['bash', 'openvpn_spinup.sh']
+        subprocess.call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+        openvpn_server_cmd = ['openvpn', '--config', 'server.conf']
+        p_server = subprocess.Popen(openvpn_server_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+        sleep(1) # Let's give OpenVPN a second to start
+
+        # Add a useless default route to the loopback interface so NM will allow starting the VPN connection.
+        # Apparently, if it doesn't own an *active connection* with a default route, it will not allow
+        # us to start the VPN client.
+        # As we set the main ethernet device as unmanaged, NM will not 'own' a default route when it starts.
+        # Unfortunately, by doing this, NM will take over the interface 'lo' and add a new yaml file to /etc/netplan
+        # We use metric 1000 so this default route will not be the preferred one.
+        self._nmcli(['con', 'mod', 'lo', 'ipv4.gateway', '192.168.5.254', 'ipv4.route-metric', '1000'])
+
+        # Create an OpenVPN connection based on the configuration found in client.conf
+        self._nmcli(['con', 'import', 'type', 'openvpn', 'file', 'client.conf'])
+
+        # At this point we should have 2 yaml files
+        # One for the tun0 NM took over and one for the VPN connection
+        self.assertEqual(self._get_number_of_yaml_files(), 2,
+                         msg='More than expected YAML files were found after creating the connection')
+
+        self._nmcli(['con', 'up', 'client'])
+        sleep(2) # Let's give NM a couple of seconds to settle down
+        # We still should have 2 files after starting the client
+        self.assertEqual(self._get_number_of_yaml_files(), 2,
+                         msg='More than expected YAML files were found after starting the connection')
+
+        self._nmcli(['con', 'down', 'client'])
+        sleep(2) # Let's give NM a couple of seconds to settle down
+        # We still should have 2 files after stopping the client
+        self.assertEqual(self._get_number_of_yaml_files(), 2,
+                         msg='More than expected YAML files were found after stopping the connection')
+
+        p_server.terminate()
+        p_server.wait()
+        # We still should have 2 files after stopping the server
+        self.assertEqual(self._get_number_of_yaml_files(), 2,
+                         msg='More than expected YAML files were found after stopping the OpenVPN server')
+
+    def test_migrate_existing_tunnel_with_nmcli(self):
+        """
+        Change an existing tunnel defined in Netplan with nmcli so it will be "imported"
+        to NM. See LP: #2016473.
+        """
+
+        netplan_yaml = '''network:
+  renderer: NetworkManager
+  tunnels:
+    wg0:
+      mode: wireguard
+      port: 51821
+      key: YCNQCAes1OTbD2ynY+aBlaA5x4ZFJhsc4co+XHpZ4FU=
+      addresses:
+        - 172.17.0.1/24
+      peers:
+        - allowed-ips: [172.17.0.0/24]
+          endpoint: 4.4.4.4:51821
+          keys:
+            public: cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI='''
+
+        netplan_yaml_path = '/etc/netplan/10-test.yaml'
+        with open(netplan_yaml_path, 'w') as f:
+            f.write(netplan_yaml)
+        os.chmod(netplan_yaml_path, mode=0o600)
+
+        self._netplan_generate()
+        self._nmcli_con_reload()
+        self._nmcli(['con', 'mod', 'netplan-wg0', 'con-name', 'netplan-wireguard-wg0'])
+
+        # After being processed by NM (and libnetplan) the new file shouldn't
+        # redefine the interface type. If it does, "netplan get" will fail
+        # when it tries to load the YAML hierarchy.
+        out = subprocess.run(['netplan', 'get'],
+                             capture_output=True, text=True)
+
+        self.assertEqual(out.returncode, 0, f'"netplan get" failed due to issues in the resulting YAML files.')
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+        self._nmcli(['con', 'del', 'netplan-wireguard-wg0'])
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_create_wireguard_tunnel_in_multiple_steps_nmcli(self):
+        """
+        Network Manager should be able to create partial Wireguard connections
+
+        See:  LP: #2016473
+        """
+
+        ret = self._nmcli(['con', 'add', 'type', 'wireguard', 'con-name', 'client-wg0', 'ifname', 'wg0', 'autoconnect', 'no'])
+        self.assertEqual(ret, 0, 'nmcli con add failed.')
+        ret = self._nmcli(['con', 'modify', 'client-wg0', 'ipv4.method', 'manual', 'ipv4.addresses', '10.1.2.3/24'])
+        self.assertEqual(ret, 0, 'nmcli ipv4 modify failed.')
+        ret = self._nmcli(['con', 'modify', 'client-wg0', 'wireguard.private-key', 'aPUcp5vHz8yMLrzk8SsDyYnV33IhE/k20e52iKJFV0A='])
+        self.assertEqual(ret, 0, 'nmcli add private key failed.')
+
+        # Use examples/python/gi/nm-wg-set to add one peer,
+        # nmcli doesn't support adding peers yet.
+        wg_peer_cmd = ['python3', 'examples/python/gi/nm-wg-set', 'client-wg0',
+                       'peer', 'cwkb7k0xDgLSnunZpFIjLJw4u+mJDDr+aBR5DqzpmgI=',
+                       'endpoint', '1.2.3.4:12345', 'allowed-ips', '192.168.0.0/24']
+        out = subprocess.run(wg_peer_cmd, capture_output=True, text=True)
+        self.assertEqual(out.returncode, 0, 'nm-wg-set failed to add the peer')
+
+    def test_import_wireguard_profile_from_file(self):
+        """
+        Network Manager should be able to import a Wireguard connection
+        from a configuration file.
+
+        See:  LP: #2016473
+        """
+        wg_profile = '''[Interface]
+PrivateKey = wFemfDk+MQbdHQnpADll/4fN/TaI7OPEMgbALP4BtF0=
+Address = 10.8.1.2/24
+DNS = 10.8.1.1
+[Peer]
+PublicKey = e3Yvr6qmGHGfOcF1wgsIWILT57FzpIgKjjP+AfcMwGI=
+AllowedIPs = 192.168.0.0/24
+Endpoint = 1.2.3.4:12345
+PersistentKeepalive = 15'''
+
+        wg_profile_path = '/etc/netplan/wg-client.conf'
+
+        with open(wg_profile_path, 'w') as f:
+            f.write(wg_profile)
+
+        ret = self._nmcli(['con', 'import', 'type', 'wireguard', 'file', wg_profile_path])
+        self.assertEqual(ret, 0, f'nmcli failed to import the Wireguard profile from {wg_profile_path}')
+
+    def test_create_wifi_connection_with_8021x(self):
+        """
+        See LP: #2016625.
+        """
+
+        openssl_cmd = [
+                'openssl', 'req', '-new', '-newkey', 'rsa:2048',
+                '-nodes', '-x509', '-subj',
+                '/C=US/ST=A/L=B/O=C/CN=www.a.com', '-keyout',
+                '/etc/netplan/a.key',  '-out', '/etc/netplan/a.crt']
+
+        subprocess.check_output(openssl_cmd, universal_newlines=True,
+                                stderr=subprocess.DEVNULL)
+
+        ret = self._nmcli(['con', 'add', 'con-name', 'eduroam',
+                           'type', 'wifi', 'ssid', 'eduroam',
+                           'wifi-sec.key-mgmt', 'wpa-eap', '802-1x.eap',
+                           'peap', '802-1x.identity', 'user@example.org',
+                           '802-1x.password', 'testing123',
+                           '802-1x.phase2-auth', 'mschapv2',
+                           '802-1x.ca-cert', '/etc/netplan/a.crt'])
+
+        self.assertEqual(ret, 0, 'nmcli failed to add connection')
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+        self._nmcli(['con', 'del', 'eduroam'])
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+    def test_create_gre_connection(self):
+        """
+        Test case for LP: #1952967.
+        """
+
+        ret = self._nmcli(['con', 'add', 'con-name', '"IP tunnel connection 1"',
+                           'type', 'ip-tunnel', 'ip-tunnel.mode', 'gre',
+                           'ifname', 'gre10', 'remote',
+                           '10.20.20.2', 'local', '10.20.20.1'])
+
+        self.assertEqual(ret, 0, 'nmcli failed to add connection')
+        self.assertEqual(self._get_number_of_yaml_files(), 1)
+        self._nmcli(['con', 'del', '"IP tunnel connection 1"'])
+        self.assertEqual(self._get_number_of_yaml_files(), 0)
+
+if __name__ == '__main__':
+    runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)
+    unittest.main(testRunner=runner)
diff -pruN 1.52.0-1/debian/tests/nm-wifi.py 1.52.0-1ubuntu1/debian/tests/nm-wifi.py
--- 1.52.0-1/debian/tests/nm-wifi.py	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/nm-wifi.py	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,403 @@
+#!/usr/bin/env python3
+# Test NetworkManager on simulated network devices
+# For an interactive shell test, run "nm-wifi.py ColdplugWifi.shell", see below
+
+__author__ = "Martin Pitt <martin.pitt@ubuntu.com>"
+__copyright__ = "(C) 2013-2025 Canonical Ltd."
+__license__ = "GPL v2 or later"
+
+import os
+import os.path
+import subprocess
+import sys
+import time
+import unittest
+
+import gi
+
+import base
+import base_wifi
+
+try:
+    from dbusmock import DBusTestCase
+except ImportError:
+    DBusTestCase = object  # dummy so that the class declaration works
+
+gi.require_version("NM", "1.0")
+from gi.repository import NM
+
+
+class ColdplugWifi(base_wifi.NetworkTestWifi):
+    """Wifi: In these tests NM starts after setting up the AP"""
+
+    # not run by default; run "nm-wifi ColdplugWifi.shell" to get this
+    @base.run_in_subprocess
+    def shell(self):
+        """Start AP and NM, then run a shell (for debugging)"""
+
+        self.setup_ap("hw_mode=b\nchannel=1\nssid=" + self.SSID, None)
+        self.start_nm(self.dev_w_client)
+        print(
+            """
+
+client interface: %s, access point interface: %s, AP SSID: "%s"
+
+You can now run commands like "nmcli dev" or "nmcli dev wifi connect '%s'".
+Logs are in '%s'. When done, exit the shell.
+
+"""
+            % (self.dev_w_client, self.dev_w_ap, self.SSID, self.SSID, self.workdir)
+        )
+        subprocess.call(["bash", "-i"])
+
+    @base.run_in_subprocess
+    def test_no_ap(self):
+        """no available access point"""
+
+        self.start_nm(self.dev_w_client)
+        # Give the interfaces a bit more time to intialized; it may be needed
+        # on ppc64el.
+        time.sleep(30)
+        self.assertEventually(self.nmclient.networking_get_enabled, timeout=20)
+
+        # state independent properties
+        self.assertEqual(self.nmdev_w.props.device_type, NM.DeviceType.WIFI)
+        self.assertTrue(self.nmdev_w.props.managed)
+        self.assertFalse(self.nmdev_w.props.firmware_missing)
+        self.assertTrue(
+            self.nmdev_w.props.udi.startswith("/sys/devices/"), self.nmdev_w.props.udi
+        )
+
+        # get_version() plausibility check
+        out = subprocess.check_output(["nmcli", "--version"], universal_newlines=True)
+        cli_version = out.split()[-1]
+        self.assertTrue(cli_version[0].isdigit())
+        self.assertEqual(self.nmclient.get_version(), cli_version)
+
+        # state dependent properties (disconnected)
+        self.assertIn(
+            self.nmdev_w.get_state(),
+            [NM.DeviceState.DISCONNECTED, NM.DeviceState.UNAVAILABLE],
+        )
+        self.assertEqual(self.nmdev_w.get_access_points(), [])
+        self.assertEqual(self.nmdev_w.get_available_connections(), [])
+
+    def test_open_b_ip4(self):
+        """Open network, 802.11b, IPv4"""
+
+        self.do_test("hw_mode=b\nchannel=1\nssid=" + self.SSID, None, 11000)
+
+    def test_open_b_ip6_raonly_tmpaddr(self):
+        """Open network, 802.11b, IPv6 with only RA, preferring temp address"""
+
+        self.do_test(
+            "hw_mode=b\nchannel=1\nssid=" + self.SSID,
+            "ra-only",
+            11000,
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_TEMP_ADDR,
+        )
+
+    def test_open_b_ip6_raonly_pubaddr(self):
+        """Open network, 802.11b, IPv6 with only RA, preferring public address"""
+
+        self.do_test(
+            "hw_mode=b\nchannel=1\nssid=" + self.SSID,
+            "ra-only",
+            11000,
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_PUBLIC_ADDR,
+        )
+
+    def test_open_b_ip6_raonly_no_pe(self):
+        """Open network, 802.11b, IPv6 with only RA, PE disabled"""
+
+        self.do_test(
+            "hw_mode=b\nchannel=1\nssid=" + self.SSID,
+            "ra-only",
+            11000,
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.DISABLED,
+        )
+
+    def test_open_b_ip6_dhcp(self):
+        """Open network, 802.11b, IPv6 with DHCP, preferring temp address"""
+
+        self.do_test(
+            "hw_mode=b\nchannel=1\nssid=" + self.SSID,
+            "",
+            11000,
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.UNKNOWN,
+        )
+
+    def test_open_g_ip4(self):
+        """Open network, 802.11g, IPv4"""
+
+        self.do_test("hw_mode=g\nchannel=1\nssid=" + self.SSID, None, 54000)
+
+    def test_wpa1_ip4(self):
+        """WPA1, 802.11g, IPv4"""
+
+        self.do_test(
+            """hw_mode=g
+channel=1
+ssid=%s
+wpa=1
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=TKIP
+wpa_passphrase=12345678
+"""
+            % self.SSID,
+            None,
+            54000,
+            base_wifi.WifiAuthenticationWPAPSK('12345678'),
+        )
+
+    def test_wpa2_ip4(self):
+        """WPA2, 802.11g, IPv4"""
+
+        self.do_test(
+            """hw_mode=g
+channel=1
+ssid=%s
+wpa=2
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+wpa_passphrase=12345678
+"""
+            % self.SSID,
+            None,
+            54000,
+            base_wifi.WifiAuthenticationWPAPSK('12345678'),
+        )
+
+    def test_wpa2_ip6(self):
+        """WPA2, 802.11g, IPv6 with only RA"""
+
+        self.do_test(
+            """hw_mode=g
+channel=1
+ssid=%s
+wpa=2
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+wpa_passphrase=12345678
+"""
+            % self.SSID,
+            "ra-only",
+            54000,
+            base_wifi.WifiAuthenticationWPAPSK('12345678'),
+            ip6_privacy=NM.SettingIP6ConfigPrivacy.PREFER_TEMP_ADDR,
+        )
+
+    def test_wpa_enterprise_authentication_ip4(self):
+        """WPA2 + 802.1x, 802.11g, IPv4"""
+
+        self.do_test(
+            """hw_mode=g
+channel=1
+ssid=%s
+auth_algs=1
+eap_server=1
+ieee8021x=1
+eapol_version=2
+wpa=2
+wpa_key_mgmt=WPA-EAP
+wpa_pairwise=TKIP
+rsn_pairwise=CCMP
+eap_user_file=/tmp/hostapd/hostapd.eap_user
+ca_cert=/tmp/hostapd/pki/ca.crt
+server_cert=/tmp/hostapd/pki/issued/server.crt
+private_key=/tmp/hostapd/pki/private/server.key
+private_key_passwd=passw0rd
+dh_file=/tmp/hostapd/pki/dh.pem
+ctrl_interface=/var/run/hostapd
+ctrl_interface_group=0
+"""
+            % self.SSID,
+            None,
+            54000,
+            base_wifi.WifiAuthenticationWPAEAP(['peap'], 'mschapv2', 'account1', 'password1')
+        )
+
+    def test_wpa_enterprise_authentication_with_client_certificate_ip4(self):
+        """WPA2 + 802.1x with client certificate, 802.11g, IPv4"""
+
+        self.do_test(
+            """hw_mode=g
+channel=1
+ssid=%s
+auth_algs=1
+eap_server=1
+ieee8021x=1
+eapol_version=2
+wpa=2
+wpa_key_mgmt=WPA-EAP
+wpa_pairwise=TKIP CCMP
+rsn_pairwise=TKIP CCMP
+eap_user_file=/tmp/hostapd/hostapd.eap_user
+ca_cert=/tmp/hostapd/pki/ca.crt
+server_cert=/tmp/hostapd/pki/issued/server.crt
+private_key=/tmp/hostapd/pki/private/server.key
+private_key_passwd=passw0rd
+dh_file=/tmp/hostapd/pki/dh.pem
+ctrl_interface=/var/run/hostapd
+ctrl_interface_group=0
+"""
+            % self.SSID,
+            None,
+            54000,
+            base_wifi.WifiAuthenticationWPAEAP(['tls'], 'tls', 'client', None, client_cert=True)
+        )
+
+    @base.run_in_subprocess
+    def test_rfkill(self):
+        """shut down connection on killswitch, restore it on unblock"""
+
+        self.setup_ap("hw_mode=b\nchannel=1\nssid=" + self.SSID, None)
+        self.start_nm(self.dev_w_client)
+        ap = self.wait_ap(timeout=1800)
+        (conn, active_conn) = self.connect_to_ap(ap, None, None, None)
+
+        self.assertFalse(self.get_rfkill(self.dev_w_client))
+        self.assertFalse(self.get_rfkill(self.dev_w_ap))
+
+        # now block the client interface
+        self.set_rfkill(self.dev_w_client, True)
+        # disabling should be fast, give it ten seconds
+        self.assertEventually(
+            lambda: self.nmdev_w.get_state() == NM.DeviceState.UNAVAILABLE, timeout=100
+        )
+
+        # dev_w_client should be down now
+        self.assert_iface_down(self.dev_w_client)
+
+        # turn it back on
+        self.set_rfkill(self.dev_w_client, False)
+        # this involves DHCP, use same timeout as for regular connection
+        self.assertEventually(
+            lambda: self.nmdev_w.get_state() == NM.DeviceState.ACTIVATED, timeout=200
+        )
+
+        # dev_w_client should be back up
+        self.assert_iface_up(self.dev_w_client, [r"inet 192.168.5.\d+/24"])
+
+
+class Hotplug(base_wifi.NetworkTestWifi):
+    """In these tests APs are set up while NM is already running"""
+
+    @base.run_in_subprocess
+    def test_auto_detect_ap(self):
+        """new AP is being detected automatically within 30s"""
+
+        self.start_nm()
+        self.setup_ap("hw_mode=b\nchannel=1\nssid=" + self.SSID, None)
+        ap = self.wait_ap(timeout=300)
+        # get_ssid returns a byte array
+        self.assertEqual(ap.get_ssid().get_data(), self.SSID.encode())
+        self.assertEqual(self.nmdev_w.get_active_access_point(), None)
+
+
+@unittest.skipIf(
+    DBusTestCase is object,
+    "WARNING: python-dbusmock not installed, skipping suspend tests; get it from https://pypi.python.org/pypi/python-dbusmock",
+)
+class Suspend(base_wifi.NetworkTestWifi, DBusTestCase):
+    """These tests run under a mock logind on a private system D-BUS"""
+
+    @classmethod
+    def setUpClass(klass):
+        klass.start_system_bus()
+        base_wifi.NetworkTestWifi.setUpClass()
+
+    @classmethod
+    def tearDownClass(klass):
+        base_wifi.NetworkTestWifi.tearDownClass()
+        DBusTestCase.tearDownClass()
+
+    def setUp(self):
+        base_wifi.NetworkTestWifi.setUp(self)
+
+        # start mock polkit and logind processes, so that we can
+        # intercept/control suspend
+        (p_polkit, self.obj_polkit) = self.spawn_server_template(
+            "polkitd", {}, stdout=subprocess.PIPE
+        )
+        # by default we are not concerned about restricting access in the tests
+        self.obj_polkit.AllowUnknown(True)
+        self.addCleanup(p_polkit.wait)
+        self.addCleanup(p_polkit.terminate)
+
+        (p_logind, self.obj_logind) = self.spawn_server_template(
+            "logind", {}, stdout=subprocess.PIPE
+        )
+        self.addCleanup(p_logind.wait)
+        self.addCleanup(p_logind.terminate)
+
+        # we have to manually start wpa_supplicant, as D-BUS activation does
+        # not happen for the fake D-BUS
+        log = os.path.join(self.workdir, "wpasupplicant.log")
+        p_wpasupp = subprocess.Popen(
+            ["wpa_supplicant", "-u", "-d", "-e", "-K", self.entropy_file, "-f", log]
+        )
+        self.addCleanup(p_wpasupp.wait)
+        self.addCleanup(p_wpasupp.terminate)
+
+    def fixme_test_active_ip4(self):
+        """suspend during active IPv4 connection"""
+
+        self.do_test(
+            "hw_mode=b\nchannel=1\nssid=" + self.SSID, None, [r"inet 192.168.5.\d+/24"]
+        )
+
+    def fixme_test_active_ip6(self):
+        """suspend during active IPv6 connection"""
+
+        self.do_test("hw_mode=b\nchannel=1\nssid=" + self.SSID, "ra-only", [r"inet6 2600::"])
+
+    #
+    # Common test code
+    #
+
+    @base.run_in_subprocess
+    def do_test(self, hostapd_conf, ipv6_mode, expected_ip_a):
+        """Actual test code, parameterized for the particular test case"""
+
+        self.setup_ap(hostapd_conf, ipv6_mode)
+        self.start_nm(self.dev_w_client)
+        ap = self.wait_ap(timeout=1800)
+        (conn, active_conn) = self.connect_to_ap(ap, None, ipv6_mode, None)
+
+        # send logind signal that we are about to suspend
+        self.obj_logind.EmitSignal("", "PrepareForSleep", "b", [True])
+
+        # disabling should be fast, give it one second
+        self.assertEventually(
+            lambda: self.nmdev_w.get_state() == NM.DeviceState.UNMANAGED, timeout=10
+        )
+        self.assert_iface_down(self.dev_w_client)
+
+        # send logind signal that we resumed
+        self.obj_logind.EmitSignal("", "PrepareForSleep", "b", [False])
+
+        # this involves DHCP, use same timeout as for regular connection
+        self.assertEventually(
+            lambda: self.nmdev_w.get_state() == NM.DeviceState.ACTIVATED, timeout=100
+        )
+
+        # dev_w_client should be back up
+        self.assert_iface_up(self.dev_w_client, expected_ip_a)
+
+
+def setUpModule():
+    base.set_up_module()
+
+def tearDownModule():
+    base.tear_down_module()
+
+
+if __name__ == "__main__":
+    # avoid unintelligible error messages when not being root
+    if os.getuid() != 0:
+       raise SystemExit("This integration test suite needs to be run as root")
+
+    # write to stdout, not stderr
+    runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)
+    unittest.main(testRunner=runner)
diff -pruN 1.52.0-1/debian/tests/prep-testbed.sh 1.52.0-1ubuntu1/debian/tests/prep-testbed.sh
--- 1.52.0-1/debian/tests/prep-testbed.sh	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/prep-testbed.sh	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -xe
+
+# only relevant on Debian
+dpkg-vendor --is Debian || exit 0
+
+# enable systemd-udevd
+mount -o remount,rw /sys
+systemctl unmask systemd-udevd.service
+systemctl start systemd-udevd.service
diff -pruN 1.52.0-1/debian/tests/urfkill-integration 1.52.0-1ubuntu1/debian/tests/urfkill-integration
--- 1.52.0-1/debian/tests/urfkill-integration	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/urfkill-integration	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,108 @@
+#!/bin/sh
+
+if dpkg --print-architecture | grep s390; then
+    echo "Skipping rfkill tests on s390 (LP: #1855009)"
+    exit 77
+fi
+
+if dpkg --print-architecture | grep i386; then
+    echo "Skipping rfkill tests on i386 (LP: #1855183)"
+    exit 77
+fi
+
+set -e
+
+echo "+++ Building / adding fake-rfkill.ko"
+make -f debian/tests/Makefile fake-rfkill
+# poor man's dependency resolver
+DEPS=$(modinfo debian/tests/fake-rfkill.ko | sed -n '/depends:/ {s/^.*://; s/[[:space:]]*$//; p}')
+[ -z "$DEPS" ] || modprobe "$DEPS"
+insmod debian/tests/fake-rfkill.ko
+
+fake_id=$(rfkill list | grep fake | awk -F: '{ print $1; }')
+echo "+++ fake-rfkill.ko is device $fake_id"
+echo
+
+
+echo "--- Testing killswitch bringup to match NM state: when URFKILL doesn't run"
+echo "+++ stopping urfkill"
+# ignore failure, only here, because urfkill probably isn't running yet.
+service urfkill stop || true
+echo "+++ unblocking device $fake_id"
+rfkill unblock $fake_id
+echo "+++ stopping network-manager"
+service NetworkManager stop || true
+echo "+++ blocking device $fake_id"
+rfkill block $fake_id
+echo "+++ starting network-manager"
+service NetworkManager start
+
+echo "+++ Waiting for the devices to settle"
+sleep 30
+
+echo -n "=== NetworkManager state should now be \"enabled\": "
+LC_MESSAGES=C nmcli radio wifi
+LC_MESSAGES=C nmcli radio wifi | grep -qc enabled
+echo
+
+echo -n "=== NM saved state: "
+grep WirelessEnabled /var/lib/NetworkManager/NetworkManager.state
+grep -qc WirelessEnabled=true /var/lib/NetworkManager/NetworkManager.state
+echo
+echo
+
+echo "--- Testing killswitch bringup when URFKILL is running: follow URfkill signals"
+echo "+++ starting urfkill"
+service urfkill start
+sleep 15
+echo "+++ blocking device $fake_id"
+rfkill block $fake_id
+rfkill list
+
+echo "+++ Waiting for the devices to settle"
+sleep 30
+
+echo -n "=== NetworkManager state should now be \"disabled\": "
+LC_MESSAGES=C nmcli radio wifi
+LC_MESSAGES=C nmcli radio wifi | grep -qc disabled
+echo
+
+echo -n "=== NM saved state: "
+grep WirelessEnabled /var/lib/NetworkManager/NetworkManager.state
+#grep -qc WirelessEnabled=false /var/lib/NetworkManager/NetworkManager.state
+echo
+echo
+
+echo "+++ Asking urfkill to unblock device $fake_id"
+dbus-send --print-reply --system --dest=org.freedesktop.URfkill /org/freedesktop/URfkill org.freedesktop.URfkill.BlockIdx uint32:$fake_id boolean:false
+sleep 5
+echo -n "=== NetworkManager state should now be \"enabled\": "
+LC_MESSAGES=C nmcli radio wifi
+LC_MESSAGES=C nmcli radio wifi | grep -qc enabled
+echo
+
+echo "+++ Asking urfkill to block device $fake_id again"
+dbus-send --print-reply --system --dest=org.freedesktop.URfkill /org/freedesktop/URfkill org.freedesktop.URfkill.BlockIdx uint32:$fake_id boolean:true
+sleep 5
+echo -n "=== NetworkManager state should now be \"disabled\": "
+LC_MESSAGES=C nmcli radio wifi
+LC_MESSAGES=C nmcli radio wifi | grep -qc disabled
+echo
+echo
+
+echo "--- Removing fake-rfkill, aggregate state should get back to enabled"
+rmmod fake-rfkill
+sleep 5
+echo -n "=== Checking that the fake device $fake_id has disappeared: "
+rfkill list | ( ! grep -qc fake || exit 1 ) && echo yes || echo no
+
+echo -n "=== NetworkManager state should now be \"enabled\": "
+LC_MESSAGES=C nmcli radio wifi
+LC_MESSAGES=C nmcli radio wifi | grep -qc enabled
+echo
+
+#cleanup
+make -f debian/tests/Makefile clean-rfkill
+
+echo OK
+exit 0
diff -pruN 1.52.0-1/debian/tests/wpa-dhcp.py 1.52.0-1ubuntu1/debian/tests/wpa-dhcp.py
--- 1.52.0-1/debian/tests/wpa-dhcp.py	1970-01-01 00:00:00.000000000 +0000
+++ 1.52.0-1ubuntu1/debian/tests/wpa-dhcp.py	2025-03-03 17:49:02.000000000 +0000
@@ -0,0 +1,232 @@
+#!/usr/bin/env python3
+# Test wpa_supplicant with a DHCP client in various modes
+
+__author__ = 'Martin Pitt <martin.pitt@ubuntu.com>'
+__copyright__ = '(C) 2013 Canonical Ltd.'
+__license__ = 'GPL v2 or later'
+
+import shutil
+import subprocess
+import sys
+import time
+import unittest
+
+import base_wifi
+
+
+class T(base_wifi.NetworkTestWifi):
+    @unittest.expectedFailure
+    def test_open_a_ip4(self):
+        '''Open network, 802.11a, IPv4'''
+
+        # channel 36 ought to work everywhere
+        self.do_test('hw_mode=a\nchannel=36\n\nssid=' + self.SSID,
+                     'ssid="%s"\nkey_mgmt=NONE' % self.SSID,
+                     None,
+                     ['54.0'])
+
+    @unittest.expectedFailure
+    def test_open_a_ip6(self):
+        '''Open network, 802.11a, IPv6'''
+
+        self.do_test('hw_mode=a\nchannel=36\n\nssid=' + self.SSID,
+                     'ssid="%s"\nkey_mgmt=NONE' % self.SSID,
+                     '',
+                     ['54.0'])
+
+    def test_open_b_ip4(self):
+        '''Open network, 802.11b, IPv4'''
+
+        self.do_test('hw_mode=b\nchannel=1\nssid=' + self.SSID,
+                     'ssid="%s"\nkey_mgmt=NONE' % self.SSID,
+                     None,
+                     ['11.0'])
+
+    def test_open_b_ip6_dhcp(self):
+        '''Open network, 802.11b, IPv6 with DHCP'''
+
+        self.do_test('hw_mode=b\nchannel=1\nssid=' + self.SSID,
+                     'ssid="%s"\nkey_mgmt=NONE' % self.SSID,
+                     '',
+                     ['11.0'])
+
+    def test_open_b_ip6_raonly(self):
+        '''Open network, 802.11b, IPv6 with only RA'''
+
+        self.do_test('hw_mode=b\nchannel=1\nssid=' + self.SSID,
+                     'ssid="%s"\nkey_mgmt=NONE' % self.SSID,
+                     'ra-only',
+                     ['11.0'])
+
+    def test_open_g_ip4(self):
+        '''Open network, 802.11g, IPv4'''
+
+        self.do_test('hw_mode=g\nchannel=1\nssid=' + self.SSID,
+                     'ssid="%s"\nkey_mgmt=NONE' % self.SSID,
+                     None,
+                     ['54.0'])
+
+    def test_wpa1_ip4(self):
+        '''WPA1, 802.11g, IPv4'''
+
+        self.do_test('''hw_mode=g
+channel=1
+ssid=%s
+wpa=1
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=TKIP
+wpa_passphrase=12345678
+''' % self.SSID,
+                     '''ssid="%s"
+psk="12345678"
+key_mgmt=WPA-PSK
+proto=WPA
+pairwise=TKIP
+group=TKIP''' % self.SSID,
+                     None,
+                     ['54.0',
+                      'Pairwise ciphers: TKIP',
+                      'Authentication suites: PSK'])
+
+    def test_wpa2_ip4(self):
+        '''WPA2, 802.11g, IPv4'''
+
+        self.do_test('''hw_mode=g
+channel=1
+ssid=%s
+wpa=2
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+wpa_passphrase=12345678
+''' % self.SSID,
+                     '''ssid="%s"
+psk="12345678"
+key_mgmt=WPA-PSK
+proto=WPA2
+pairwise=CCMP
+group=CCMP''' % self.SSID,
+                     None,
+                     ['54.0',
+                      'Pairwise ciphers: CCMP',
+                      'Authentication suites: PSK'])
+
+    def test_wpa2_ip6(self):
+        '''WPA2, 802.11g, IPv6'''
+
+        self.do_test('''hw_mode=g
+channel=1
+ssid=%s
+wpa=2
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+wpa_passphrase=12345678
+''' % self.SSID,
+                     '''ssid="%s"
+psk="12345678"
+key_mgmt=WPA-PSK
+proto=WPA2
+pairwise=CCMP
+group=CCMP''' % self.SSID,
+                     '',
+                     ['54.0',
+                      'Pairwise ciphers: CCMP',
+                      'Authentication suites: PSK'])
+
+    #
+    # Common for all tests
+    #
+
+    def do_test(self, hostapd_conf, wpa_conf, ipv6, exp_iw_scan):
+        self.setup_ap(hostapd_conf, ipv6)
+        self.check_ssid_avail(exp_iw_scan)
+        self.start_wpasupp(wpa_conf)
+        self.check_iw_link()
+        self.check_communication(ipv6)
+        self.check_address(ipv6)
+
+    def check_ssid_avail(self, expected_strings):
+        subprocess.check_call(['ip', 'link', 'set', self.dev_w_client, 'up'])
+        out = subprocess.check_output(['iw', 'dev', self.dev_w_client, 'scan'],
+                                      universal_newlines=True)
+        # down it again, wpa_supplicant is supposed to up it by itself
+        subprocess.check_call(['ip', 'link', 'set', self.dev_w_client, 'down'])
+
+        self.assertRegex(out, r'SSID: ' + self.SSID)
+        for s in expected_strings:
+            self.assertRegex(out, s)
+
+    def check_iw_link(self):
+        tries = 10
+        while tries > 0:
+            out = subprocess.check_output(['iw', 'dev', self.dev_w_client, 'link'],
+                                          universal_newlines=True)
+            if 'SSID' in out:
+                break
+            tries -= 1
+            time.sleep(1)
+        else:
+            self.fail('timed out on iwconfig showing connected status')
+
+        self.assertRegex(out, r'Connected to ' + self.mac_w_ap)
+        self.assertRegex(out, r'SSID: ' + self.SSID)
+
+    def check_communication(self, ipv6_mode):
+        '''Verify that communication works between AP and client
+
+        This proves that wpa_supplicant set up a working link. We use a DHCP
+        request for IPv4 and IPv6 in DHCP mode. For IPv6 in other (i.
+        e. ra-only/slaac) modes, check that dnsmasq received a router solicit
+        and sends a router advertisement.
+        '''
+        if ipv6_mode is not None:
+            self.poll_text(self.dnsmasq_log, 'RTR-SOLICIT(%s)' % self.dev_w_ap, timeout=50)
+            self.poll_text(self.dnsmasq_log, 'RTR-ADVERT(%s)' % self.dev_w_ap, timeout=5)
+
+        # stop here for non-DHCP modes in IPv6
+        if ipv6_mode not in (None, '', 'slaac'):
+            return
+
+        if ipv6_mode is not None:
+            mode = '-6'
+        else:
+            mode = '-4'
+
+        # run DHCP client on client
+        shutil.rmtree('/var/lib/dhcpcd/', ignore_errors=True)
+        out = subprocess.check_output(['dhcpcd', mode, '-w', '-d', '-A', self.dev_w_client],
+                                      universal_newlines=True, timeout=10,
+                                      stderr=subprocess.STDOUT)
+        # stop DHCP client
+        subprocess.call(['dhcpcd', mode, '-x', '-q', self.dev_w_client],
+                        stderr=subprocess.STDOUT)
+
+        if ipv6_mode is not None:
+            self.assertRegex(out, r'adding address 2600::')
+            self.assertRegex(out, r'BOUND6', out)
+        else:
+            self.assertRegex(out, r'acknowledged 192.168.5.\d+ from 192.168.5.1')
+            self.assertRegex(out, r'leased 192.168.5.')
+
+    def check_address(self, ipv6_mode):
+        '''Verify that the interface got an appropriate address assigned'''
+
+        out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.dev_w_client],
+                                      universal_newlines=True)
+        self.assertRegex(out, r'state UP')
+        if ipv6_mode is None:
+            self.assertRegex(out, r'inet 192.168.5.\d+/24')
+        else:
+            if not ipv6_mode:
+                # has global address from our DHCP server
+                self.assertRegex(out, r'inet6 2600::[0-9a-z]+/\d')
+            else:
+                # has address with our prefix and MAC
+                self.assertRegex(out, r'inet6 2600::ff:fe00:[0-9a-z]+/64 scope global (?:tentative )?(?:mngtmpaddr )?dynamic')
+
+            # has a link-local address
+            self.assertRegex(out, r'inet6 fe80::ff:fe00:[0-9a-z:]+/64 scope link')
+
+
+# write to stdout, not stderr
+runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)
+unittest.main(testRunner=runner)
