diff --git a/NetworkManager.spec b/NetworkManager.spec index 1e47cad..c8512d0 100644 --- a/NetworkManager.spec +++ b/NetworkManager.spec @@ -19,7 +19,7 @@ Name: NetworkManager Summary: Network connection manager and user applications Epoch: 1 Version: 0.9.9.0 -Release: 26%{snapshot}%{?dist} +Release: 27%{snapshot}%{?dist} Group: System Environment/Base License: GPLv2+ URL: http://www.gnome.org/projects/NetworkManager/ @@ -56,6 +56,16 @@ Patch26: rh1036132-VPN-active-con-info.patch Patch27: rh1031574-primary-connection.patch Patch28: physical-port-id.patch Patch29: gi-fix-for-ipv6.patch +Patch30: fix-read-phys-port-id.patch +Patch31: export-missing-libnm-glib-funcs.patch +Patch32: get-nameservers.patch +Patch33: get-ip-examples.patch +Patch34: rem-con-constructed.patch +Patch35: rh1057738-dbus-clean-exit.patch +Patch36: rh1048046-dhcp-no-ipv6.patch +Patch37: rh983325-add-route-for-dhcp-server.patch +Patch38: rh1030068-vpn-tunnel-interface.patch +Patch39: core-log-ipv6-commit.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -208,6 +218,16 @@ deployments. %patch27 -p1 -b .primary-connection %patch28 -p1 -b .physical-port-id %patch29 -p1 -b .gi-fix-for-ipv6 +%patch30 -p1 -b .fix-read-phys-port-id +%patch31 -p1 -b .export-missing-libnm-glib-funcs +%patch32 -p1 -b .get-nameservers +%patch33 -p1 -b .get-ip-examples +%patch34 -p1 -b .rem-con-constructed +%patch35 -p1 -b .rh1057738-dbus-clean-exit +%patch36 -p1 -b .rh1048046-dhcp-no-ipv6 +%patch37 -p1 -b .rh983325-add-route-for-dhcp-server +%patch38 -p1 -b .rh1030068-vpn-tunnel-interface +%patch39 -p1 -b .core-log-ipv6-commit %build @@ -406,6 +426,17 @@ fi %config %{_sysconfdir}/%{name}/conf.d/00-server.conf %changelog +* Tue Jan 28 2014 Jiří Klimeš - 0.9.9.0-27.git20131003 +- core: fix reading physical port id for sysfs +- libnm-glib: export get_gateway() and get_searches() functions +- libnm-glib: new functions for bindings to get nameservers +- libnm-glib: chain up the parent constructed() of NMRemoteConnection +- core: exit cleanly if D-Bus cannot be initialized (rh #1057738) +- dhcp: don't add an IPv6 address if one wasn't given (rh #1048046) +- core: Add host route for DHCP4 server if outside assigned subnet (bgo #721767) (rh #983325) +- vpn: handle missing tunnel interface for IP-based VPNs (bgo #721724) (rh #1030068) (rh #865883) +- core: only log about IPv6 Commit the first time (rh #1044757) + * Tue Jan 21 2014 Jiří Klimeš - 0.9.9.0-26.git20131003 - core: improve handling of NPAR/SR-IOV devices (rh #804527) - libnm-glib: add NMDevice:physical-port-id property diff --git a/core-log-ipv6-commit.patch b/core-log-ipv6-commit.patch new file mode 100644 index 0000000..5cbeb00 --- /dev/null +++ b/core-log-ipv6-commit.patch @@ -0,0 +1,94 @@ +From 13f4a00d4d490fb65f93c246d1c93ed56a47213f Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Thu, 23 Jan 2014 13:02:16 -0600 +Subject: [PATCH] core: only log about IPv6 Commit the first time +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since IPv6 configuration gets updated every time a router advertisement +comes in, it can lead NM to continuously logging: + +NetworkManager: Activation (eth0) Stage 5 of 5 (IPv6 Commit) scheduled... +NetworkManager: Activation (eth0) Stage 5 of 5 (IPv6 Commit) started... +NetworkManager: Activation (eth0) Stage 5 of 5 (IPv6 Commit) complete. + +that's annoying. So after the initial configuration is done, make +subsequent IPv6 Commit log messages debug instead of info. + +Signed-off-by: Jiří Klimeš +--- + src/devices/nm-device.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 035434e..4684efe 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -335,8 +335,6 @@ static gboolean nm_device_set_ip6_config (NMDevice *dev, + gboolean commit, + NMDeviceStateReason *reason); + +-static gboolean nm_device_activate_ip6_config_commit (gpointer user_data); +- + static gboolean check_connection_available (NMDevice *device, NMConnection *connection); + + static gboolean spec_match_list (NMDevice *device, const GSList *specs); +@@ -4232,6 +4230,7 @@ nm_device_activate_ip6_config_commit (gpointer user_data) + { + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); ++ guint level = (priv->ip6_state == IP_DONE) ? LOGL_DEBUG : LOGL_INFO; + NMActRequest *req; + const char *iface; + NMConnection *connection; +@@ -4241,8 +4240,7 @@ nm_device_activate_ip6_config_commit (gpointer user_data) + activation_source_clear (self, FALSE, AF_INET6); + + iface = nm_device_get_iface (self); +- nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) started...", +- iface); ++ nm_log (LOGD_DEVICE, level, "Activation (%s) Stage 5 of 5 (IPv6 Commit) started...", iface); + + req = nm_device_get_act_request (self); + g_assert (req); +@@ -4262,14 +4260,13 @@ nm_device_activate_ip6_config_commit (gpointer user_data) + if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) + nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); + } else { +- nm_log_info (LOGD_DEVICE | LOGD_IP6, ++ nm_log_warn (LOGD_DEVICE | LOGD_IP6, + "Activation (%s) Stage 5 of 5 (IPv6 Commit) failed", + iface); + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + } + +- nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) complete.", +- iface); ++ nm_log (LOGD_DEVICE, level, "Activation (%s) Stage 5 of 5 (IPv6 Commit) complete.", iface); + + return FALSE; + } +@@ -4277,13 +4274,16 @@ nm_device_activate_ip6_config_commit (gpointer user_data) + void + nm_device_activate_schedule_ip6_config_result (NMDevice *self) + { ++ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); ++ guint level = (priv->ip6_state == IP_DONE) ? LOGL_DEBUG : LOGL_INFO; ++ + g_return_if_fail (NM_IS_DEVICE (self)); + + activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6); + +- nm_log_info (LOGD_DEVICE | LOGD_IP6, +- "Activation (%s) Stage 5 of 5 (IPv6 Commit) scheduled...", +- nm_device_get_iface (self)); ++ nm_log (LOGD_DEVICE | LOGD_IP6, level, ++ "Activation (%s) Stage 5 of 5 (IPv6 Commit) scheduled...", ++ nm_device_get_iface (self)); + } + + gboolean +-- +1.7.11.7 + diff --git a/export-missing-libnm-glib-funcs.patch b/export-missing-libnm-glib-funcs.patch new file mode 100644 index 0000000..4820929 --- /dev/null +++ b/export-missing-libnm-glib-funcs.patch @@ -0,0 +1,45 @@ +From 3391fa810ca323203b036a68af7f3c5802280918 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= +Date: Wed, 22 Jan 2014 10:03:44 +0100 +Subject: [PATCH] libnm-glib: export missing get_gateway() and get_searches() + functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +They were added by db9b7e10aca5456ec4960b75617e032209b98bc1 commit. + +Signed-off-by: Jiří Klimeš +--- + libnm-glib/libnm-glib.ver | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver +index cb7b599..bf69db4 100644 +--- a/libnm-glib/libnm-glib.ver ++++ b/libnm-glib/libnm-glib.ver +@@ -215,8 +215,10 @@ global: + nm_dhcp6_config_new; + nm_ip4_config_get_addresses; + nm_ip4_config_get_domains; ++ nm_ip4_config_get_gateway; + nm_ip4_config_get_nameservers; + nm_ip4_config_get_routes; ++ nm_ip4_config_get_searches; + nm_ip4_config_get_type; + nm_ip4_config_get_wins_servers; + nm_ip4_config_new; +@@ -224,8 +226,10 @@ global: + nm_ip6_address_object_array_get_type; + nm_ip6_config_get_addresses; + nm_ip6_config_get_domains; ++ nm_ip6_config_get_gateway; + nm_ip6_config_get_nameservers; + nm_ip6_config_get_routes; ++ nm_ip6_config_get_searches; + nm_ip6_config_get_type; + nm_ip6_config_new; + nm_ip6_route_object_array_get_type; +-- +1.7.11.7 + diff --git a/fix-read-phys-port-id.patch b/fix-read-phys-port-id.patch new file mode 100644 index 0000000..93252f5 --- /dev/null +++ b/fix-read-phys-port-id.patch @@ -0,0 +1,32 @@ +From 041f449a910a48716bc88fa56287c4213a2dcb11 Mon Sep 17 00:00:00 2001 +From: Dan Winship +Date: Wed, 22 Jan 2014 13:20:18 -0500 +Subject: [PATCH] platform: fix linux nm_platform_link_get_physical_port_id() + (rh #804527) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It was reading the wrong property name + +Signed-off-by: Jiří Klimeš +--- + src/platform/nm-linux-platform.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c +index 83cbc49..8e85c59 100644 +--- a/src/platform/nm-linux-platform.c ++++ b/src/platform/nm-linux-platform.c +@@ -1765,7 +1765,7 @@ link_get_physical_port_id (NMPlatform *platform, int ifindex) + if (!ifname) + return NULL; + +- path = g_strdup_printf ("/sys/class/net/%s/physical_port_id", ifname); ++ path = g_strdup_printf ("/sys/class/net/%s/phys_port_id", ifname); + if (g_file_test (path, G_FILE_TEST_EXISTS)) + id = sysctl_get (platform, path); + else +-- +1.7.11.7 + diff --git a/get-ip-examples.patch b/get-ip-examples.patch new file mode 100644 index 0000000..fa49253 --- /dev/null +++ b/get-ip-examples.patch @@ -0,0 +1,98 @@ +From 85272df6eb89682a3d13022281085b97527955e1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= +Date: Wed, 22 Jan 2014 15:40:22 +0100 +Subject: [PATCH] examples: update get_ips.py python example for DNS + information +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + +Signed-off-by: Jiří Klimeš +--- + examples/python/gi/get_ips.py | 44 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 40 insertions(+), 4 deletions(-) + +diff --git a/examples/python/gi/get_ips.py b/examples/python/gi/get_ips.py +index b1e59e2..6903b6d 100755 +--- a/examples/python/gi/get_ips.py ++++ b/examples/python/gi/get_ips.py +@@ -24,8 +24,8 @@ import sys, socket, struct + from gi.repository import GLib, NetworkManager, NMClient + + # +-# This example shows how to get get addresses and routes from NMIP4Config and NMIP6Config +-# (got out of NMDevice) ++# This example shows how to get addresses, routes and DNS information ++# from NMIP4Config and NMIP6Config (got out of NMDevice) + # + + def show_addresses(self, family): +@@ -59,7 +59,6 @@ def show_addresses(self, family): + socket.inet_ntop(family, gateway_struct)) + + +- + def show_routes(self, family): + if (family == socket.AF_INET): + ip_cfg = self.get_ip4_config() +@@ -70,7 +69,7 @@ def show_routes(self, family): + print("None") + return + +- nm_routes = ip_cfg.get_routes() ++ nm_routes = ip_cfg.get_routes() + if len(nm_routes) == 0: + print("None") + return +@@ -93,6 +92,33 @@ def show_routes(self, family): + metric) + + ++def show_dns(self, family): ++ if (family == socket.AF_INET): ++ ip_cfg = self.get_ip4_config() ++ else: ++ ip_cfg = self.get_ip6_config() ++ ++ if ip_cfg is None: ++ print("None") ++ return ++ ++ if (family == socket.AF_INET): ++ print ("Domains: %s") % (ip_cfg.get_domains()) ++ print ("Searches: %s") % (ip_cfg.get_searches()) ++ print("Nameservers:") ++ nameservers = ip_cfg.get_nameservers() ++ for dns in nameservers: ++ print socket.inet_ntop(family, struct.pack("=I", dns)) ++ else: ++ print ("Domains: %s") % (ip_cfg.get_domains()) ++ print ("Searches: %s") % (ip_cfg.get_searches()) ++ print("Nameservers:") ++ num = ip_cfg.get_num_nameservers() ++ for i in range(0,num): ++ dns = ip_cfg.get_nameserver(i) ++ print socket.inet_ntop(family, dns) ++ ++ + if __name__ == "__main__": + if len(sys.argv) != 2: + sys.exit('Usage: %s ' % sys.argv[0]) +@@ -125,3 +151,13 @@ if __name__ == "__main__": + show_routes(dev, socket.AF_INET6) + print + ++ print "IPv4 DNS:" ++ print("------------") ++ show_dns(dev, socket.AF_INET) ++ print ++ ++ print "IPv6 DNS:" ++ print("------------") ++ show_dns(dev, socket.AF_INET6) ++ print ++ +-- +1.7.11.7 + diff --git a/get-nameservers.patch b/get-nameservers.patch new file mode 100644 index 0000000..b7e7ace --- /dev/null +++ b/get-nameservers.patch @@ -0,0 +1,145 @@ +From 8ee4f58e9ee67df2ef761a691dec55c6008ad4ff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= +Date: Wed, 22 Jan 2014 15:31:56 +0100 +Subject: [PATCH] libnm-glib: additional functions to get nameservers (rh + #1056146) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit adds two new functions for introspection users to get nameservers: +guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config) +const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint32 idx) +The existing function can't be used due to GObject introspection limitations: +const GSList *nm_ip6_config_get_nameservers (NMIP6Config *config); + +https://bugzilla.redhat.com/show_bug.cgi?id=1056146 + +Signed-off-by: Jiří Klimeš +--- + libnm-glib/libnm-glib.ver | 2 ++ + libnm-glib/nm-ip6-config.c | 52 +++++++++++++++++++++++++++++++++++++++++++++- + libnm-glib/nm-ip6-config.h | 16 +++++++------- + 3 files changed, 62 insertions(+), 8 deletions(-) + +diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver +index bf69db4..9f0db93 100644 +--- a/libnm-glib/libnm-glib.ver ++++ b/libnm-glib/libnm-glib.ver +@@ -227,7 +227,9 @@ global: + nm_ip6_config_get_addresses; + nm_ip6_config_get_domains; + nm_ip6_config_get_gateway; ++ nm_ip6_config_get_nameserver; + nm_ip6_config_get_nameservers; ++ nm_ip6_config_get_num_nameservers; + nm_ip6_config_get_routes; + nm_ip6_config_get_searches; + nm_ip6_config_get_type; +diff --git a/libnm-glib/nm-ip6-config.c b/libnm-glib/nm-ip6-config.c +index 01e2cae..7c9cfca 100644 +--- a/libnm-glib/nm-ip6-config.c ++++ b/libnm-glib/nm-ip6-config.c +@@ -18,7 +18,7 @@ + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. +- * Copyright (C) 2008 - 2011 Red Hat, Inc. ++ * Copyright (C) 2008 - 2014 Red Hat, Inc. + */ + + #include +@@ -192,6 +192,56 @@ nm_ip6_config_get_addresses (NMIP6Config *config) + return NM_IP6_CONFIG_GET_PRIVATE (config)->addresses; + } + ++/** ++ * nm_ip6_config_get_num_nameservers: ++ * @config: a #NMIP6Config ++ * ++ * Gets the number of the domain name servers in the configuration. ++ * ++ * Returns: the number of domain name servers ++ * ++ * Since: 0.9.10 ++ **/ ++guint32 ++nm_ip6_config_get_num_nameservers (NMIP6Config *config) ++{ ++ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), 0); ++ ++ _nm_object_ensure_inited (NM_OBJECT (config)); ++ return g_slist_length (NM_IP6_CONFIG_GET_PRIVATE (config)->nameservers); ++} ++ ++/** ++ * nm_ip6_config_get_nameserver: ++ * @config: a #NMIP6Config ++ * @idx: index of the nameserver to return ++ * ++ * Gets the domain name server at index @idx in the configuration. ++ * ++ * Returns: (array fixed-size=16) (element-type guint8) (transfer none): ++ * the IPv6 address of domain name server at index @iidx ++ * ++ * Since: 0.9.10 ++ **/ ++const struct in6_addr * ++nm_ip6_config_get_nameserver (NMIP6Config *config, guint32 idx) ++{ ++ NMIP6ConfigPrivate *priv; ++ GSList *item; ++ guint32 i = 0; ++ ++ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); ++ ++ _nm_object_ensure_inited (NM_OBJECT (config)); ++ priv = NM_IP6_CONFIG_GET_PRIVATE (config); ++ ++ for (item = priv->nameservers; item && i < idx; i++) ++ item = item->next; ++ ++ g_return_val_if_fail (item, NULL); ++ return item ? (const struct in6_addr *) item->data : NULL; ++} ++ + /* FIXME: like in libnm_util, in6_addr is not introspectable, so skipping here */ + /** + * nm_ip6_config_get_nameservers: (skip) +diff --git a/libnm-glib/nm-ip6-config.h b/libnm-glib/nm-ip6-config.h +index a71d74b..b6198fa 100644 +--- a/libnm-glib/nm-ip6-config.h ++++ b/libnm-glib/nm-ip6-config.h +@@ -18,7 +18,7 @@ + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2007 - 2008 Novell, Inc. +- * Copyright (C) 2008 Red Hat, Inc. ++ * Copyright (C) 2008 - 2014 Red Hat, Inc. + */ + + #ifndef NM_IP6_CONFIG_H +@@ -65,12 +65,14 @@ GType nm_ip6_config_get_type (void); + + GObject *nm_ip6_config_new (DBusGConnection *connection, const char *object_path); + +-const char * nm_ip6_config_get_gateway (NMIP6Config *config); +-const GSList * nm_ip6_config_get_addresses (NMIP6Config *config); +-const GSList * nm_ip6_config_get_routes (NMIP6Config *config); +-const GSList * nm_ip6_config_get_nameservers (NMIP6Config *config); +-const GPtrArray *nm_ip6_config_get_domains (NMIP6Config *config); +-const GPtrArray *nm_ip6_config_get_searches (NMIP6Config *config); ++const char * nm_ip6_config_get_gateway (NMIP6Config *config); ++const GSList * nm_ip6_config_get_addresses (NMIP6Config *config); ++const GSList * nm_ip6_config_get_routes (NMIP6Config *config); ++guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config); ++const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, guint32 idx); ++const GSList * nm_ip6_config_get_nameservers (NMIP6Config *config); ++const GPtrArray * nm_ip6_config_get_domains (NMIP6Config *config); ++const GPtrArray * nm_ip6_config_get_searches (NMIP6Config *config); + + G_END_DECLS + +-- +1.7.11.7 + diff --git a/rem-con-constructed.patch b/rem-con-constructed.patch new file mode 100644 index 0000000..ff5de61 --- /dev/null +++ b/rem-con-constructed.patch @@ -0,0 +1,31 @@ +From df4c9347fc85ec2aa7ddc67e0ff39bc1d56f669a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= +Date: Mon, 27 Jan 2014 17:36:30 +0100 +Subject: [PATCH] libnm-glib: chain up the parent constructed() of + NMRemoteConnection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + + +Signed-off-by: Jiří Klimeš +--- + libnm-glib/nm-remote-connection.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c +index 73a2cc8..27baebd 100644 +--- a/libnm-glib/nm-remote-connection.c ++++ b/libnm-glib/nm-remote-connection.c +@@ -508,6 +508,8 @@ constructed (GObject *object) + { + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); + ++ G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructed (object); ++ + g_assert (priv->bus); + g_assert (nm_connection_get_path (NM_CONNECTION (object))); + +-- +1.7.11.7 + diff --git a/rh1030068-vpn-tunnel-interface.patch b/rh1030068-vpn-tunnel-interface.patch new file mode 100644 index 0000000..ffb0e00 --- /dev/null +++ b/rh1030068-vpn-tunnel-interface.patch @@ -0,0 +1,293 @@ +From d7c369712b9e6298d62303899e372ab7d27a92d9 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Mon, 23 Dec 2013 12:21:09 -0600 +Subject: [PATCH] vpn: handle missing tunnel interface for IP-based VPNs (bgo + #721724) (rh #1030068) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +IPSec-based VPNs that use the kernel IPSec stack don't have tunnel +interfaces, and the IP details (address, routes) get added directly +to the parent network device. NetworkManager previously required +a tunnel interface and failed the VPN if one was not provided. + +When no tunnel interface is passed, construct the VPN IP configuration +using available details and pass that to the NMDevice as the VPN IP +config. The device will merge that config with its own and apply +any configuration that the kernel/VPN has not already applied. + +https://bugzilla.gnome.org/show_bug.cgi?id=721724 +https://bugzilla.redhat.com/show_bug.cgi?id=1030068 + +https://bugzilla.redhat.com/show_bug.cgi?id=865883 +https://bugzilla.redhat.com/show_bug.cgi?id=845599 + +Signed-off-by: Jiří Klimeš +--- + src/nm-policy.c | 15 +++-- + src/vpn-manager/nm-vpn-connection.c | 112 ++++++++++++++++++++++-------------- + 2 files changed, 79 insertions(+), 48 deletions(-) + +diff --git a/src/nm-policy.c b/src/nm-policy.c +index 92ec1ab..090cd04 100644 +--- a/src/nm-policy.c ++++ b/src/nm-policy.c +@@ -655,17 +655,21 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) + in_addr_t int_gw = nm_vpn_connection_get_ip4_internal_gateway (vpn); + int mss = nm_ip4_config_get_mss (ip4_config); + ++ /* If no VPN interface, use the parent interface */ ++ if (ip_ifindex <= 0) ++ ip_ifindex = parent_ifindex; ++ + if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, 0, mss)) { + nm_platform_ip4_route_add (parent_ifindex, gw_addr, 32, 0, 0, parent_mss); +- if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, 0, mss)) { ++ if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, 0, mss)) + nm_log_err (LOGD_IP4 | LOGD_VPN, "Failed to set default route."); +- } + } + + default_device = nm_vpn_connection_get_parent_device (vpn); + } else { + int mss = nm_ip4_config_get_mss (ip4_config); + ++ g_assert (ip_iface); + if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, 0, mss)) { + nm_platform_ip4_route_add (ip_ifindex, gw_addr, 32, 0, 0, mss); + if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, 0, mss)) { +@@ -845,6 +849,10 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) + if (!int_gw) + int_gw = &in6addr_any; + ++ /* If no VPN interface, use the parent interface */ ++ if (ip_ifindex <= 0) ++ ip_ifindex = parent_ifindex; ++ + if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, 0, mss)) { + nm_platform_ip6_route_add (parent_ifindex, *gw_addr, 128, in6addr_any, 0, parent_mss); + if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, 0, mss)) { +@@ -858,9 +866,8 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) + + if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, 0, mss)) { + nm_platform_ip6_route_add (ip_ifindex, *gw_addr, 128, in6addr_any, 0, mss); +- if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, 0, mss)) { ++ if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, 0, mss)) + nm_log_err (LOGD_IP6, "Failed to set default route."); +- } + } + + default_device6 = best; +diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c +index 8541f10..f1d7d46 100644 +--- a/src/vpn-manager/nm-vpn-connection.c ++++ b/src/vpn-manager/nm-vpn-connection.c +@@ -301,13 +301,13 @@ device_state_changed (NMActiveConnection *active, + } + + static void +-add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) ++add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32 vpn_gw) + { + NMIP4Config *parent_config; + guint32 parent_gw; + NMPlatformIP4Route route; +- NMIP4Config *vpn4_config; + ++ g_return_if_fail (NM_IS_IP4_CONFIG (config)); + g_return_if_fail (NM_IS_DEVICE (parent_device)); + g_return_if_fail (vpn_gw != 0); + +@@ -321,8 +321,6 @@ add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) + if (!parent_gw) + return; + +- vpn4_config = nm_ip4_config_new (); +- + memset (&route, 0, sizeof (route)); + route.network = vpn_gw; + route.plen = 32; +@@ -335,7 +333,7 @@ add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) + if (nm_ip4_config_destination_is_direct (parent_config, vpn_gw, 32)) + route.gateway = 0; + +- nm_ip4_config_add_route (vpn4_config, &route); ++ nm_ip4_config_add_route (config, &route); + + /* Ensure there's a route to the parent device's gateway through the + * parent device, since if the VPN claims the default route and the VPN +@@ -346,21 +344,19 @@ add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) + route.network = parent_gw; + route.plen = 32; + +- nm_ip4_config_add_route (vpn4_config, &route); +- +- nm_device_set_vpn4_config (parent_device, vpn4_config); +- g_object_unref (vpn4_config); ++ nm_ip4_config_add_route (config, &route); + } + + static void +-add_ip6_vpn_gateway_route (NMDevice *parent_device, ++add_ip6_vpn_gateway_route (NMIP6Config *config, ++ NMDevice *parent_device, + const struct in6_addr *vpn_gw) + { + NMIP6Config *parent_config; + const struct in6_addr *parent_gw; + NMPlatformIP6Route route; +- NMIP6Config *vpn6_config; + ++ g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_if_fail (NM_IS_DEVICE (parent_device)); + g_return_if_fail (vpn_gw != NULL); + +@@ -370,8 +366,6 @@ add_ip6_vpn_gateway_route (NMDevice *parent_device, + if (!parent_gw) + return; + +- vpn6_config = nm_ip6_config_new (); +- + memset (&route, 0, sizeof (route)); + route.network = *vpn_gw; + route.plen = 128; +@@ -384,7 +378,7 @@ add_ip6_vpn_gateway_route (NMDevice *parent_device, + if (nm_ip6_config_destination_is_direct (parent_config, vpn_gw, 128)) + route.gateway = in6addr_any; + +- nm_ip6_config_add_route (vpn6_config, &route); ++ nm_ip6_config_add_route (config, &route); + + /* Ensure there's a route to the parent device's gateway through the + * parent device, since if the VPN claims the default route and the VPN +@@ -395,10 +389,7 @@ add_ip6_vpn_gateway_route (NMDevice *parent_device, + route.network = *parent_gw; + route.plen = 128; + +- nm_ip6_config_add_route (vpn6_config, &route); +- +- nm_device_set_vpn6_config (parent_device, vpn6_config); +- g_object_unref (vpn6_config); ++ nm_ip6_config_add_route (config, &route); + } + + NMVPNConnection * +@@ -601,7 +592,7 @@ print_vpn_config (NMVPNConnection *connection) + ip6_address_to_string (priv->ip6_external_gw)); + } + +- nm_log_info (LOGD_VPN, "Tunnel Device: %s", priv->ip_iface); ++ nm_log_info (LOGD_VPN, "Tunnel Device: %s", priv->ip_iface ? priv->ip_iface : "(none)"); + + if (priv->ip4_config) { + nm_log_info (LOGD_VPN, "IPv4 configuration:"); +@@ -692,25 +683,54 @@ nm_vpn_connection_apply_config (NMVPNConnection *connection) + nm_vpn_connection_apply_config (NMVPNConnection *connection) + { + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); ++ NMIP4Config *vpn4_parent_config = NULL; ++ NMIP6Config *vpn6_parent_config = NULL; + +- nm_platform_link_set_up (priv->ip_ifindex); ++ if (priv->ip_ifindex > 0) { ++ nm_platform_link_set_up (priv->ip_ifindex); + +- if (priv->ip4_config) { +- if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex, 0)) +- return FALSE; ++ if (priv->ip4_config) { ++ if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex, 0)) ++ return FALSE; ++ } ++ ++ if (priv->ip6_config) { ++ if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex, 0)) ++ return FALSE; ++ } ++ ++ if (priv->ip4_config) ++ vpn4_parent_config = nm_ip4_config_new (); ++ if (priv->ip6_config) ++ vpn6_parent_config = nm_ip6_config_new (); ++ } else { ++ /* If the VPN didn't return a network interface, it is a route-based ++ * VPN (like kernel IPSec) and all IP addressing and routing should ++ * be done on the parent interface instead. ++ */ ++ ++ if (priv->ip4_config) ++ vpn4_parent_config = g_object_ref (priv->ip4_config); ++ if (priv->ip6_config) ++ vpn6_parent_config = g_object_ref (priv->ip6_config); + } + +- if (priv->ip6_config) { +- if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex, 0)) +- /* FIXME: remove ip4 config */ +- return FALSE; ++ if (vpn4_parent_config) { ++ /* Add any explicit route to the VPN gateway through the parent device */ ++ if (priv->ip4_external_gw) ++ add_ip4_vpn_gateway_route (vpn4_parent_config, priv->parent_dev, priv->ip4_external_gw); ++ ++ nm_device_set_vpn4_config (priv->parent_dev, vpn4_parent_config); ++ g_object_unref (vpn4_parent_config); + } ++ if (vpn6_parent_config) { ++ /* Add any explicit route to the VPN gateway through the parent device */ ++ if (priv->ip6_external_gw) ++ add_ip6_vpn_gateway_route (vpn6_parent_config, priv->parent_dev, priv->ip6_external_gw); + +- /* Add any explicit route to the VPN gateway through the parent device */ +- if (priv->ip4_external_gw) +- add_ip4_vpn_gateway_route (priv->parent_dev, priv->ip4_external_gw); +- if (priv->ip6_external_gw) +- add_ip6_vpn_gateway_route (priv->parent_dev, priv->ip6_external_gw); ++ nm_device_set_vpn6_config (priv->parent_dev, vpn6_parent_config); ++ g_object_unref (vpn6_parent_config); ++ } + + nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) complete.", + nm_connection_get_id (priv->connection)); +@@ -768,21 +788,25 @@ process_generic_config (NMVPNConnection *connection, + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + GValue *val; + ++ g_clear_pointer (&priv->ip_iface, g_free); ++ + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_TUNDEV); +- if (val) +- priv->ip_iface = g_strdup (g_value_get_string (val)); +- else { +- nm_log_err (LOGD_VPN, "invalid or missing tunnel device received!"); +- nm_vpn_connection_config_maybe_complete (connection, FALSE); +- return FALSE; ++ if (val) { ++ const char *tmp = g_value_get_string (val); ++ ++ /* Backwards compat with NM-openswan */ ++ if (g_strcmp0 (tmp, "_none_") != 0) ++ priv->ip_iface = g_strdup (tmp); + } + +- /* Grab the interface index for address/routing operations */ +- priv->ip_ifindex = nm_platform_link_get_ifindex (priv->ip_iface); +- if (!priv->ip_ifindex) { +- nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface); +- nm_vpn_connection_config_maybe_complete (connection, FALSE); +- return FALSE; ++ if (priv->ip_iface) { ++ /* Grab the interface index for address/routing operations */ ++ priv->ip_ifindex = nm_platform_link_get_ifindex (priv->ip_iface); ++ if (!priv->ip_ifindex) { ++ nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface); ++ nm_vpn_connection_config_maybe_complete (connection, FALSE); ++ return FALSE; ++ } + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_BANNER); +-- +1.7.11.7 + diff --git a/rh1048046-dhcp-no-ipv6.patch b/rh1048046-dhcp-no-ipv6.patch new file mode 100644 index 0000000..dff0a3d --- /dev/null +++ b/rh1048046-dhcp-no-ipv6.patch @@ -0,0 +1,61 @@ +From a9f1d121783a7f3c65c9f47d3419b5a8a255fe47 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Thu, 23 Jan 2014 12:16:02 -0600 +Subject: [PATCH] dhcp: don't add an IPv6 address if one wasn't given (rh + #1048046) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In information-only mode (where RA is providing addresses), DHCPv6 +may not give an address. NetworkManager was adding a blank one +anyway, which is invalid. Don't do that. + +Signed-off-by: Jiří Klimeš +--- + src/dhcp-manager/nm-dhcp-client.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c +index 75cd818..57298c8 100644 +--- a/src/dhcp-manager/nm-dhcp-client.c ++++ b/src/dhcp-manager/nm-dhcp-client.c +@@ -1404,6 +1404,12 @@ ip6_options_to_config (NMDHCPClient *self) + + ip6_config = nm_ip6_config_new (); + ++ str = g_hash_table_lookup (priv->options, "new_dhcp_lease_time"); ++ if (str) { ++ address.lifetime = address.preferred = strtoul (str, NULL, 10); ++ nm_log_info (LOGD_DHCP6, " lease time %d", address.lifetime); ++ } ++ + str = g_hash_table_lookup (priv->options, "new_ip6_address"); + if (str) { + if (!inet_pton (AF_INET6, str, &tmp_addr)) { +@@ -1413,21 +1419,13 @@ ip6_options_to_config (NMDHCPClient *self) + } + + address.address = tmp_addr; ++ nm_ip6_config_add_address (ip6_config, &address); + nm_log_info (LOGD_DHCP6, " address %s", str); +- + } else if (priv->info_only == FALSE) { + /* No address in Managed mode is a hard error */ + goto error; + } + +- str = g_hash_table_lookup (priv->options, "new_dhcp_lease_time"); +- if (str) { +- address.lifetime = address.preferred = strtoul (str, NULL, 10); +- nm_log_info (LOGD_DHCP6, " lease time %d", address.lifetime); +- } +- +- nm_ip6_config_add_address (ip6_config, &address); +- + str = g_hash_table_lookup (priv->options, "new_host_name"); + if (str) + nm_log_info (LOGD_DHCP6, " hostname '%s'", str); +-- +1.7.11.7 + diff --git a/rh1057738-dbus-clean-exit.patch b/rh1057738-dbus-clean-exit.patch new file mode 100644 index 0000000..94bd64c --- /dev/null +++ b/rh1057738-dbus-clean-exit.patch @@ -0,0 +1,203 @@ +From e62b212be3b51b0dc31fd12ea70d78358164063e Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Fri, 24 Jan 2014 12:49:57 -0600 +Subject: [PATCH] core: exit cleanly if D-Bus cannot be initialized (rh + #1057738) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Instead of crashing, let's exit cleanly. + +Signed-off-by: Jiří Klimeš +--- + src/nm-manager.c | 90 ++++++++++++++++++++++++++++++-------------------------- + 1 file changed, 49 insertions(+), 41 deletions(-) + +diff --git a/src/nm-manager.c b/src/nm-manager.c +index e6ff8d5..1545e72 100644 +--- a/src/nm-manager.c ++++ b/src/nm-manager.c +@@ -217,6 +217,7 @@ typedef struct { + + NMDBusManager *dbus_mgr; + guint dbus_connection_changed_id; ++ gboolean prop_filter_added; + NMAtmManager *atm_mgr; + NMRfkillManager *rfkill_mgr; + NMBluezManager *bluez_mgr; +@@ -250,7 +251,6 @@ typedef struct { + GHashTable *nm_bridges; + + gboolean startup; +- gboolean disposed; + } NMManagerPrivate; + + #define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) +@@ -4503,6 +4503,16 @@ nm_manager_new (NMSettings *settings, + + priv = NM_MANAGER_GET_PRIVATE (singleton); + ++ bus = nm_dbus_manager_get_connection (priv->dbus_mgr); ++ if (!bus) { ++ nm_log_err (LOGD_CORE, "Failed to initialize D-Bus connection"); ++ g_object_unref (singleton); ++ return NULL; ++ } ++ ++ dbus_connection = dbus_g_connection_get_connection (bus); ++ g_assert (dbus_connection); ++ + priv->policy = nm_policy_new (singleton, settings); + g_signal_connect (priv->policy, "notify::" NM_POLICY_DEFAULT_IP4_DEVICE, + G_CALLBACK (policy_default_device_changed), singleton); +@@ -4517,16 +4527,12 @@ nm_manager_new (NMSettings *settings, + g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE, + G_CALLBACK (connectivity_changed), singleton); + +- bus = nm_dbus_manager_get_connection (priv->dbus_mgr); +- g_assert (bus); +- dbus_connection = dbus_g_connection_get_connection (bus); +- g_assert (dbus_connection); +- + if (!dbus_connection_add_filter (dbus_connection, prop_filter, singleton, NULL)) { + nm_log_err (LOGD_CORE, "failed to register DBus connection filter"); + g_object_unref (singleton); + return NULL; +- } ++ } ++ priv->prop_filter_added = TRUE; + + priv->settings = g_object_ref (settings); + +@@ -4614,14 +4620,9 @@ dispose (GObject *object) + DBusConnection *dbus_connection; + GSList *iter; + +- if (priv->disposed) { +- G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); +- return; +- } +- priv->disposed = TRUE; +- + g_slist_foreach (priv->auth_chains, (GFunc) nm_auth_chain_unref, NULL); + g_slist_free (priv->auth_chains); ++ priv->auth_chains = NULL; + + nm_auth_changed_func_unregister (authority_changed_cb, manager); + +@@ -4635,8 +4636,7 @@ dispose (GObject *object) + + for (iter = priv->active_connections; iter; iter = g_slist_next (iter)) + active_connection_removed (manager, NM_ACTIVE_CONNECTION (iter->data)); +- g_slist_free (priv->active_connections); +- priv->active_connections = NULL; ++ g_clear_pointer (&priv->active_connections, g_slist_free); + g_clear_object (&priv->primary_connection); + g_clear_object (&priv->activating_connection); + +@@ -4644,12 +4644,14 @@ dispose (GObject *object) + + g_free (priv->hostname); + +- g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_default_device_changed), singleton); +- g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_activating_device_changed), singleton); +- g_object_unref (priv->policy); ++ if (priv->policy) { ++ g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_default_device_changed), singleton); ++ g_signal_handlers_disconnect_by_func (priv->policy, G_CALLBACK (policy_activating_device_changed), singleton); ++ g_clear_object (&priv->policy); ++ } + +- g_object_unref (priv->settings); +- g_object_unref (priv->vpn_manager); ++ g_clear_object (&priv->settings); ++ g_clear_object (&priv->vpn_manager); + + if (priv->modem_added_id) { + g_source_remove (priv->modem_added_id); +@@ -4659,39 +4661,42 @@ dispose (GObject *object) + g_source_remove (priv->modem_removed_id); + priv->modem_removed_id = 0; + } +- g_object_unref (priv->modem_manager); ++ g_clear_object (&priv->modem_manager); + + /* Unregister property filter */ +- bus = nm_dbus_manager_get_connection (priv->dbus_mgr); +- if (bus) { +- dbus_connection = dbus_g_connection_get_connection (bus); +- g_assert (dbus_connection); +- dbus_connection_remove_filter (dbus_connection, prop_filter, manager); ++ if (priv->dbus_mgr) { ++ bus = nm_dbus_manager_get_connection (priv->dbus_mgr); ++ if (bus) { ++ dbus_connection = dbus_g_connection_get_connection (bus); ++ if (dbus_connection && priv->prop_filter_added) { ++ dbus_connection_remove_filter (dbus_connection, prop_filter, manager); ++ priv->prop_filter_added = FALSE; ++ } ++ } ++ g_signal_handler_disconnect (priv->dbus_mgr, priv->dbus_connection_changed_id); ++ priv->dbus_mgr = NULL; + } +- g_signal_handler_disconnect (priv->dbus_mgr, priv->dbus_connection_changed_id); +- priv->dbus_mgr = NULL; +- +- if (priv->bluez_mgr) +- g_object_unref (priv->bluez_mgr); +- +- if (priv->aipd_proxy) +- g_object_unref (priv->aipd_proxy); + +- if (priv->sleep_monitor) +- g_object_unref (priv->sleep_monitor); ++ g_clear_object (&priv->bluez_mgr); ++ g_clear_object (&priv->aipd_proxy); ++ g_clear_object (&priv->sleep_monitor); + + if (priv->fw_monitor) { +- if (priv->fw_monitor_id) ++ if (priv->fw_monitor_id) { + g_signal_handler_disconnect (priv->fw_monitor, priv->fw_monitor_id); ++ priv->fw_monitor_id = 0; ++ } + +- if (priv->fw_changed_id) ++ if (priv->fw_changed_id) { + g_source_remove (priv->fw_changed_id); ++ priv->fw_changed_id = 0; ++ } + + g_file_monitor_cancel (priv->fw_monitor); +- g_object_unref (priv->fw_monitor); ++ g_clear_object (&priv->fw_monitor); + } + +- g_slist_free (priv->factories); ++ g_clear_pointer (&priv->factories, g_slist_free); + + if (priv->timestamp_update_id) { + g_source_remove (priv->timestamp_update_id); +@@ -4945,14 +4950,17 @@ dbus_connection_changed_cb (NMDBusManager *dbus_mgr, + gpointer user_data) + { + NMManager *self = NM_MANAGER (user_data); ++ gboolean success = FALSE; + + if (dbus_connection) { + /* Register property filter on new connection; there's no reason this + * should fail except out-of-memory or program error; if it does fail + * then there's no Manager property access control, which is bad. + */ +- g_assert (dbus_connection_add_filter (dbus_connection, prop_filter, self, NULL)); ++ success = dbus_connection_add_filter (dbus_connection, prop_filter, self, NULL); ++ g_assert (success); + } ++ NM_MANAGER_GET_PRIVATE (self)->prop_filter_added = success; + } + + static void +-- +1.7.11.7 + diff --git a/rh983325-add-route-for-dhcp-server.patch b/rh983325-add-route-for-dhcp-server.patch new file mode 100644 index 0000000..bbbee4e --- /dev/null +++ b/rh983325-add-route-for-dhcp-server.patch @@ -0,0 +1,83 @@ +From 31fe84e467732463eabc8f70c2a419008e7a227c Mon Sep 17 00:00:00 2001 +From: Scott Shambarger +Date: Thu, 9 Jan 2014 14:26:53 -0800 +Subject: [PATCH] core: Add host route for DHCP4 server if outside assigned + subnet (bgo #721767) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some ISP's provide leases from central servers that are on different +subnets that the address offered. If the host does not configure the +interface as the default route, the dhcp server may not be reachable +via unicast, and a host specific route is needed. + +https://bugzilla.gnome.org/show_bug.cgi?id=721767 +https://bugzilla.redhat.com/show_bug.cgi?id=983325 + +Signed-off-by: Thomas Haller +Signed-off-by: Jiří Klimeš +--- + src/dhcp-manager/nm-dhcp-client.c | 39 +++++++++++++++++++++++++++++++++++++-- + 1 file changed, 37 insertions(+), 2 deletions(-) + +diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c +index edea8f8..75cd818 100644 +--- a/src/dhcp-manager/nm-dhcp-client.c ++++ b/src/dhcp-manager/nm-dhcp-client.c +@@ -1200,8 +1200,8 @@ ip4_options_to_config (NMDHCPClient *self) + + for (s = routers; *s; s++) { + /* FIXME: how to handle multiple routers? */ +- if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { +- nm_ip4_config_set_gateway (ip4_config, tmp_addr); ++ if (inet_pton (AF_INET, *s, &gwaddr) > 0) { ++ nm_ip4_config_set_gateway (ip4_config, gwaddr); + nm_log_info (LOGD_DHCP4, " gateway %s", *s); + break; + } else +@@ -1211,6 +1211,41 @@ ip4_options_to_config (NMDHCPClient *self) + } + } + ++ /* ++ * RFC 2132, section 9.7 ++ * DHCP clients use the contents of the 'server identifier' field ++ * as the destination address for any DHCP messages unicast to ++ * the DHCP server. ++ * ++ * Some ISP's provide leases from central servers that are on ++ * different subnets that the address offered. If the host ++ * does not configure the interface as the default route, the ++ * dhcp server may not be reachable via unicast, and a host ++ * specific route is needed. ++ **/ ++ str = g_hash_table_lookup (priv->options, "new_dhcp_server_identifier"); ++ if (str) { ++ if (inet_pton (AF_INET, str, &tmp_addr) > 0) { ++ NMPlatformIP4Route route; ++ guint32 mask = nm_utils_ip4_prefix_to_netmask (address.plen); ++ ++ nm_log_info (LOGD_DHCP4, " server identifier %s", str); ++ if ((tmp_addr & mask) != (address.address & mask)) { ++ /* DHCP server not on assigned subnet, route needed */ ++ memset (&route, 0, sizeof (route)); ++ route.network = tmp_addr; ++ route.plen = 32; ++ /* this will be a device route if gwaddr is 0 */ ++ route.gateway = gwaddr; ++ nm_ip4_config_add_route (ip4_config, &route); ++ nm_log_dbg (LOGD_IP, "adding route for server identifier: %s", ++ nm_platform_ip4_route_to_string (&route)); ++ } ++ } ++ else ++ nm_log_warn (LOGD_DHCP4, "ignoring invalid server identifier '%s'", str); ++ } ++ + str = g_hash_table_lookup (priv->options, "new_dhcp_lease_time"); + if (str) { + address.lifetime = address.preferred = strtoul (str, NULL, 10); +-- +1.7.11.7 +