diff options
Diffstat (limited to 'src')
70 files changed, 1933 insertions, 1167 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 94e1a8c0..c8caefb0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -159,6 +159,10 @@ NetworkManager_SOURCES = \ nm-manager-auth.h \ nm-netlink-monitor.c \ nm-netlink-monitor.h \ + nm-netlink-utils.c \ + nm-netlink-utils.h \ + nm-netlink-compat.h \ + nm-netlink-compat.c \ nm-activation-request.c \ nm-activation-request.h \ nm-properties-changed-signal.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 5d9567ed..9bb66f55 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -116,6 +116,8 @@ am_NetworkManager_OBJECTS = NetworkManager-nm-call-store.$(OBJEXT) \ NetworkManager-nm-manager.$(OBJEXT) \ NetworkManager-nm-manager-auth.$(OBJEXT) \ NetworkManager-nm-netlink-monitor.$(OBJEXT) \ + NetworkManager-nm-netlink-utils.$(OBJEXT) \ + NetworkManager-nm-netlink-compat.$(OBJEXT) \ NetworkManager-nm-activation-request.$(OBJEXT) \ NetworkManager-nm-properties-changed-signal.$(OBJEXT) \ NetworkManager-wpa.$(OBJEXT) \ @@ -338,6 +340,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ @@ -582,6 +590,10 @@ NetworkManager_SOURCES = \ nm-manager-auth.h \ nm-netlink-monitor.c \ nm-netlink-monitor.h \ + nm-netlink-utils.c \ + nm-netlink-utils.h \ + nm-netlink-compat.h \ + nm-netlink-compat.c \ nm-activation-request.c \ nm-activation-request.h \ nm-properties-changed-signal.c \ @@ -847,7 +859,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-ip6-config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-manager-auth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-netlink-compat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-netlink-monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-netlink-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-policy-hostname.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-policy-hosts.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-policy.Po@am__quote@ @@ -1341,6 +1355,38 @@ NetworkManager-nm-netlink-monitor.obj: nm-netlink-monitor.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-monitor.obj `if test -f 'nm-netlink-monitor.c'; then $(CYGPATH_W) 'nm-netlink-monitor.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-monitor.c'; fi` +NetworkManager-nm-netlink-utils.o: nm-netlink-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-utils.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo -c -o NetworkManager-nm-netlink-utils.o `test -f 'nm-netlink-utils.c' || echo '$(srcdir)/'`nm-netlink-utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo $(DEPDIR)/NetworkManager-nm-netlink-utils.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-netlink-utils.c' object='NetworkManager-nm-netlink-utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-utils.o `test -f 'nm-netlink-utils.c' || echo '$(srcdir)/'`nm-netlink-utils.c + +NetworkManager-nm-netlink-utils.obj: nm-netlink-utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-utils.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo -c -o NetworkManager-nm-netlink-utils.obj `if test -f 'nm-netlink-utils.c'; then $(CYGPATH_W) 'nm-netlink-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-utils.Tpo $(DEPDIR)/NetworkManager-nm-netlink-utils.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-netlink-utils.c' object='NetworkManager-nm-netlink-utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-utils.obj `if test -f 'nm-netlink-utils.c'; then $(CYGPATH_W) 'nm-netlink-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-utils.c'; fi` + +NetworkManager-nm-netlink-compat.o: nm-netlink-compat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-compat.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo -c -o NetworkManager-nm-netlink-compat.o `test -f 'nm-netlink-compat.c' || echo '$(srcdir)/'`nm-netlink-compat.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo $(DEPDIR)/NetworkManager-nm-netlink-compat.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-netlink-compat.c' object='NetworkManager-nm-netlink-compat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-compat.o `test -f 'nm-netlink-compat.c' || echo '$(srcdir)/'`nm-netlink-compat.c + +NetworkManager-nm-netlink-compat.obj: nm-netlink-compat.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-netlink-compat.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo -c -o NetworkManager-nm-netlink-compat.obj `if test -f 'nm-netlink-compat.c'; then $(CYGPATH_W) 'nm-netlink-compat.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-compat.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-netlink-compat.Tpo $(DEPDIR)/NetworkManager-nm-netlink-compat.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-netlink-compat.c' object='NetworkManager-nm-netlink-compat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-netlink-compat.obj `if test -f 'nm-netlink-compat.c'; then $(CYGPATH_W) 'nm-netlink-compat.c'; else $(CYGPATH_W) '$(srcdir)/nm-netlink-compat.c'; fi` + NetworkManager-nm-activation-request.o: nm-activation-request.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-activation-request.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-activation-request.Tpo -c -o NetworkManager-nm-activation-request.o `test -f 'nm-activation-request.c' || echo '$(srcdir)/'`nm-activation-request.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-activation-request.Tpo $(DEPDIR)/NetworkManager-nm-activation-request.Po diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index f96f2aad..451de6d0 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -26,6 +26,7 @@ #include <string.h> #include <unistd.h> #include <ctype.h> +#include <stdlib.h> #include "NetworkManagerUtils.h" #include "nm-utils.h" @@ -43,9 +44,6 @@ #include "nm-setting-wireless-security.h" #include "nm-manager-auth.h" -#include <netlink/addr.h> -#include <netinet/in.h> - /* * nm_ethernet_address_is_valid * diff --git a/src/backends/Makefile.in b/src/backends/Makefile.in index 2f489e75..6776e343 100644 --- a/src/backends/Makefile.in +++ b/src/backends/Makefile.in @@ -232,6 +232,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/backends/NetworkManagerGeneric.c b/src/backends/NetworkManagerGeneric.c index 8f16066f..89b8a46d 100644 --- a/src/backends/NetworkManagerGeneric.c +++ b/src/backends/NetworkManagerGeneric.c @@ -34,7 +34,9 @@ #include "nm-system.h" #include "NetworkManagerUtils.h" #include "nm-logging.h" +#include "nm-netlink-compat.h" #include "nm-netlink-monitor.h" +#include "nm-netlink-utils.h" /* Because of a bug in libnl, rtnl.h should be included before route.h */ #include <netlink/route/rtnl.h> @@ -50,15 +52,13 @@ */ void nm_generic_enable_loopback (void) { - struct nl_handle * nlh = NULL; + struct nl_sock * nlh = NULL; struct rtnl_addr * addr = NULL; struct nl_addr * nl_addr = NULL; guint32 binaddr = 0; int iface_idx = -1; int err; - nm_system_device_set_up_down_with_iface ("lo", TRUE, NULL); - nlh = nm_netlink_get_default_handle (); if (!nlh) return; @@ -67,6 +67,8 @@ void nm_generic_enable_loopback (void) if (iface_idx < 0) return; + nm_system_iface_set_up (iface_idx, TRUE, NULL); + addr = rtnl_addr_alloc (); if (!addr) return; @@ -90,10 +92,10 @@ void nm_generic_enable_loopback (void) rtnl_addr_set_scope (addr, RT_SCOPE_HOST); rtnl_addr_set_label (addr, "lo"); - if ((err = rtnl_addr_add (nlh, addr, 0)) < 0) { - if (err != -EEXIST) { - nm_log_warn (LOGD_CORE, "error %d returned from rtnl_addr_add():\n%s", err, nl_geterror()); - } + err = rtnl_addr_add (nlh, addr, 0); + if (err && (err != -NLE_EXIST)) { + nm_log_warn (LOGD_CORE, "error setting loopback address: (%d) %s", + err, nl_geterror (err)); } out: if (addr) diff --git a/src/bluez-manager/Makefile.in b/src/bluez-manager/Makefile.in index 1336b7ec..e141456a 100644 --- a/src/bluez-manager/Makefile.in +++ b/src/bluez-manager/Makefile.in @@ -189,6 +189,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in index dd557056..990c9363 100644 --- a/src/dhcp-manager/Makefile.in +++ b/src/dhcp-manager/Makefile.in @@ -237,6 +237,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in index 7e875055..5e3167bb 100644 --- a/src/dhcp-manager/tests/Makefile.in +++ b/src/dhcp-manager/tests/Makefile.in @@ -187,6 +187,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/dns-manager/Makefile.in b/src/dns-manager/Makefile.in index aad1c562..acc700e1 100644 --- a/src/dns-manager/Makefile.in +++ b/src/dns-manager/Makefile.in @@ -190,6 +190,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/dns-manager/nm-dns-bind.c b/src/dns-manager/nm-dns-bind.c index fc7af776..55fce030 100644 --- a/src/dns-manager/nm-dns-bind.c +++ b/src/dns-manager/nm-dns-bind.c @@ -297,7 +297,8 @@ update (NMDnsPlugin *plugin, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, - const char *hostname) + const char *hostname, + const char *iface) { NMDnsBind *self = NM_DNS_BIND (plugin); NMDnsBindPrivate *priv = NM_DNS_BIND_GET_PRIVATE (self); diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 9cc01978..27672088 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -133,23 +133,56 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split) return TRUE; } -static gboolean -ip6_addr_to_string (const struct in6_addr *addr, char *buf, size_t buflen) +#define IP6_ADDR_BUFLEN (INET6_ADDRSTRLEN + 50) + +static char * +ip6_addr_to_string (const struct in6_addr *addr, const char *iface) { - memset (buf, 0, buflen); + char *buf, *p; + + /* allocate enough space for the address + interface name */ + buf = g_malloc0 (IP6_ADDR_BUFLEN + 1); /* inet_ntop is probably supposed to do this for us, but it doesn't */ - if (IN6_IS_ADDR_V4MAPPED (addr)) - return !!inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, buflen); + if (IN6_IS_ADDR_V4MAPPED (addr)) { + if (!inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, IP6_ADDR_BUFLEN)) + goto error; + return buf; + } - return !!inet_ntop (AF_INET6, addr, buf, buflen); + if (!inet_ntop (AF_INET6, addr, buf, IP6_ADDR_BUFLEN)) + goto error; + + /* In the case of addr being a link-local address, inet_ntop can either + * return an address with scope identifier already in place (like + * fe80::202:b3ff:fe8d:7aaf%wlan0) or it returns an address without + * scope identifier at all (like fe80::202:b3ff:fe8d:7aaf) + */ + p = strchr (buf, '%'); + if (p) { + /* If we got a scope identifier, we need to replace the '%' + * with '@', since dnsmasq supports '%' in server= addresses + * only since version 2.58 and up + */ + *p = '@'; + } else if (IN6_IS_ADDR_LINKLOCAL (addr)) { + /* If we got no scope identifier at all append the interface name */ + strncat (buf, "@", IP6_ADDR_BUFLEN - strlen (buf)); + strncat (buf, iface, IP6_ADDR_BUFLEN - strlen (buf)); + } + + return buf; + +error: + g_free (buf); + return NULL; } static gboolean -add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) +add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split, const char *iface) { - char buf[INET6_ADDRSTRLEN + 1]; const struct in6_addr *addr; + char *buf; int n, i; gboolean added = FALSE; @@ -159,7 +192,8 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) * the first nameserver here. */ addr = nm_ip6_config_get_nameserver (ip6, 0); - if (!ip6_addr_to_string (addr, &buf[0], sizeof (buf))) + buf = ip6_addr_to_string (addr, iface); + if (!buf) return FALSE; /* searches are preferred over domains */ @@ -181,6 +215,8 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) added = TRUE; } } + + g_free (buf); } /* If no searches or domains, just add the namservers */ @@ -188,8 +224,11 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split) n = nm_ip6_config_get_num_nameservers (ip6); for (i = 0; i < n; i++) { addr = nm_ip6_config_get_nameserver (ip6, i); - if (ip6_addr_to_string (addr, &buf[0], sizeof (buf))) + buf = ip6_addr_to_string (addr, iface); + if (buf) { g_string_append_printf (str, "server=%s\n", buf); + g_free (buf); + } } } @@ -201,7 +240,8 @@ update (NMDnsPlugin *plugin, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, - const char *hostname) + const char *hostname, + const char *iface) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); GString *conf; @@ -226,7 +266,7 @@ update (NMDnsPlugin *plugin, if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), TRUE); else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE); + add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE, iface); } /* Now add interface configs without split DNS */ @@ -234,7 +274,7 @@ update (NMDnsPlugin *plugin, if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); + add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE, iface); } /* And any other random configs */ @@ -242,7 +282,7 @@ update (NMDnsPlugin *plugin, if (NM_IS_IP4_CONFIG (iter->data)) add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE); else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE); + add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE, iface); } /* Write out the config file */ diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 49cd74e5..0203f2bb 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -711,7 +711,8 @@ update_dns (NMDnsManager *self, vpn_configs, dev_configs, other_configs, - priv->hostname)) { + priv->hostname, + iface)) { nm_log_warn (LOGD_DNS, "DNS: plugin %s update failed", plugin_name); /* If the plugin failed to update, we shouldn't write out a local diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c index ae230ada..e997948e 100644 --- a/src/dns-manager/nm-dns-plugin.c +++ b/src/dns-manager/nm-dns-plugin.c @@ -55,7 +55,8 @@ nm_dns_plugin_update (NMDnsPlugin *self, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, - const char *hostname) + const char *hostname, + const char *iface) { g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE); @@ -63,7 +64,8 @@ nm_dns_plugin_update (NMDnsPlugin *self, vpn_configs, dev_configs, other_configs, - hostname); + hostname, + iface); } static gboolean diff --git a/src/dns-manager/nm-dns-plugin.h b/src/dns-manager/nm-dns-plugin.h index d4298b86..37dd7336 100644 --- a/src/dns-manager/nm-dns-plugin.h +++ b/src/dns-manager/nm-dns-plugin.h @@ -53,7 +53,8 @@ typedef struct { const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, - const char *hostname); + const char *hostname, + const char *iface); /* Subclasses should override and return TRUE if they start a local * caching nameserver that listens on localhost and would block any @@ -91,7 +92,8 @@ gboolean nm_dns_plugin_update (NMDnsPlugin *self, const GSList *vpn_configs, const GSList *dev_configs, const GSList *other_configs, - const char *hostname); + const char *hostname, + const char *iface); /* For subclasses/plugins */ diff --git a/src/dnsmasq-manager/Makefile.in b/src/dnsmasq-manager/Makefile.in index 89f55e5e..62c44c01 100644 --- a/src/dnsmasq-manager/Makefile.in +++ b/src/dnsmasq-manager/Makefile.in @@ -186,6 +186,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/ip6-manager/Makefile.in b/src/ip6-manager/Makefile.in index 33539f51..dd596a81 100644 --- a/src/ip6-manager/Makefile.in +++ b/src/ip6-manager/Makefile.in @@ -187,6 +187,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c index 4a5dee58..c7341390 100644 --- a/src/ip6-manager/nm-ip6-manager.c +++ b/src/ip6-manager/nm-ip6-manager.c @@ -27,6 +27,8 @@ #include "nm-ip6-manager.h" #include "nm-netlink-monitor.h" +#include "nm-netlink-utils.h" +#include "nm-netlink-compat.h" #include "NetworkManagerUtils.h" #include "nm-marshal.h" #include "nm-logging.h" @@ -44,7 +46,7 @@ typedef struct { NMNetlinkMonitor *monitor; GHashTable *devices; - struct nl_handle *nlh; + struct nl_sock *nlh; struct nl_cache *addr_cache, *route_cache; guint netlink_id; @@ -549,11 +551,12 @@ process_addr (NMIP6Manager *manager, struct nl_msg *msg) device = nm_ip6_manager_get_device (manager, rtnl_addr_get_ifindex (rtnladdr)); if (!device) { nm_log_dbg (LOGD_IP6, "ignoring message for unknown device"); + rtnl_addr_put (rtnladdr); return NULL; } old_size = nl_cache_nitems (priv->addr_cache); - nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL); + nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL, NULL); rtnl_addr_put (rtnladdr); /* The kernel will re-notify us of automatically-added addresses @@ -589,11 +592,12 @@ process_route (NMIP6Manager *manager, struct nl_msg *msg) device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute)); if (!device) { nm_log_dbg (LOGD_IP6, "ignoring message for unknown device"); + rtnl_route_put (rtnlroute); return NULL; } old_size = nl_cache_nitems (priv->route_cache); - nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL); + nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL); rtnl_route_put (rtnlroute); /* As above in process_addr */ @@ -620,6 +624,11 @@ process_prefix (NMIP6Manager *manager, struct nl_msg *msg) nm_log_dbg (LOGD_IP6, "processing netlink new prefix message"); + if (!nlmsg_valid_hdr (nlmsg_hdr (msg), sizeof(*pmsg))) { + nm_log_dbg (LOGD_IP6, "ignoring invalid prefix message"); + return NULL; + } + pmsg = (struct prefixmsg *) NLMSG_DATA (nlmsg_hdr (msg)); device = nm_ip6_manager_get_device (manager, pmsg->prefix_ifindex); @@ -907,6 +916,13 @@ process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg) ndmsg = (struct nduseroptmsg *) NLMSG_DATA (nlmsg_hdr (msg)); + if (!nlmsg_valid_hdr (nlmsg_hdr (msg), sizeof (*ndmsg)) || + nlmsg_datalen (nlmsg_hdr (msg)) < + (ndmsg->nduseropt_opts_len + sizeof (*ndmsg))) { + nm_log_dbg (LOGD_IP6, "ignoring invalid nduseropt message"); + return NULL; + } + if (ndmsg->nduseropt_family != AF_INET6 || ndmsg->nduseropt_icmp_type != ND_ROUTER_ADVERT || ndmsg->nduseropt_icmp_code != 0) { @@ -966,6 +982,19 @@ process_newlink (NMIP6Manager *manager, struct nl_msg *msg) struct nlattr *pi[IFLA_INET6_MAX + 1]; int err; + /* FIXME: we have to do this manually for now since libnl doesn't yet + * support the IFLA_PROTINFO attribute of NEWLINK messages. When it does, + * we can get rid of this function and just grab IFLA_PROTINFO from + * nm_ip6_device_sync_from_netlink(), then get the IFLA_INET6_FLAGS out of + * the PROTINFO. + */ + err = nlmsg_parse (hdr, sizeof (*ifi), tb, IFLA_MAX, link_policy); + if (err < 0) { + nm_log_dbg (LOGD_IP6, "ignoring invalid newlink netlink message " + "while parsing PROTINFO attribute"); + return NULL; + } + ifi = nlmsg_data (hdr); if (ifi->ifi_family != AF_INET6) { nm_log_dbg (LOGD_IP6, "ignoring netlink message family %d", ifi->ifi_family); @@ -979,18 +1008,6 @@ process_newlink (NMIP6Manager *manager, struct nl_msg *msg) return NULL; } - /* FIXME: we have to do this manually for now since libnl doesn't yet - * support the IFLA_PROTINFO attribute of NEWLINK messages. When it does, - * we can get rid of this function and just grab IFLA_PROTINFO from - * nm_ip6_device_sync_from_netlink(), then get the IFLA_INET6_FLAGS out of - * the PROTINFO. - */ - - err = nlmsg_parse (hdr, sizeof (*ifi), tb, IFLA_MAX, link_policy); - if (err < 0) { - nm_log_dbg (LOGD_IP6, "(%s): error parsing PROTINFO attribute", device->iface); - return NULL; - } if (!tb[IFLA_PROTINFO]) { nm_log_dbg (LOGD_IP6, "(%s): message had no PROTINFO attribute", device->iface); return NULL; @@ -1248,7 +1265,7 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex) nm_ip6_route_set_dest (ip6route, dest); nm_ip6_route_set_prefix (ip6route, rtnl_route_get_dst_len (rtnlroute)); nm_ip6_route_set_next_hop (ip6route, gateway); - metric = rtnl_route_get_metric (rtnlroute, 1); + rtnl_route_get_metric(rtnlroute, 1, &metric); if (metric != UINT_MAX) nm_ip6_route_set_metric (ip6route, metric); nm_ip6_config_take_route (config, ip6route); @@ -1344,8 +1361,10 @@ nm_ip6_manager_init (NMIP6Manager *manager) G_CALLBACK (netlink_notification), manager); priv->nlh = nm_netlink_get_default_handle (); - priv->addr_cache = rtnl_addr_alloc_cache (priv->nlh); - priv->route_cache = rtnl_route_alloc_cache (priv->nlh); + rtnl_addr_alloc_cache (priv->nlh, &priv->addr_cache); + g_warn_if_fail (priv->addr_cache != NULL); + rtnl_route_alloc_cache (priv->nlh, NETLINK_ROUTE, NL_AUTO_PROVIDE, &priv->route_cache); + g_warn_if_fail (priv->route_cache != NULL); } static void diff --git a/src/logging/Makefile.in b/src/logging/Makefile.in index a85578d9..951cd2b6 100644 --- a/src/logging/Makefile.in +++ b/src/logging/Makefile.in @@ -183,6 +183,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/modem-manager/Makefile.in b/src/modem-manager/Makefile.in index 2a054f70..5f83035f 100644 --- a/src/modem-manager/Makefile.in +++ b/src/modem-manager/Makefile.in @@ -189,6 +189,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 1823e5e6..debfbdf7 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -640,7 +640,7 @@ static void real_deactivate (NMModem *self, NMDevice *device) { NMModemPrivate *priv; - const char *iface; + int ifindex; g_return_if_fail (self != NULL); g_return_if_fail (NM_IS_MODEM (self)); @@ -679,11 +679,11 @@ real_deactivate (NMModem *self, NMDevice *device) break; case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_DHCP: - iface = nm_device_get_ip_iface (device); + ifindex = nm_device_get_ip_ifindex (device); /* FIXME: use AF_UNSPEC here when we have IPv6 support */ - nm_system_device_flush_routes_with_iface (iface, AF_INET); - nm_system_device_flush_addresses_with_iface (iface); - nm_system_device_set_up_down_with_iface (iface, FALSE, NULL); + nm_system_iface_flush_routes (ifindex, AF_INET); + nm_system_iface_flush_addresses (ifindex, AF_UNSPEC); + nm_system_iface_set_up (ifindex, FALSE, NULL); break; default: nm_log_err (LOGD_MB, "unknown IP method %d", priv->ip_method); @@ -775,7 +775,7 @@ nm_modem_hw_is_up (NMModem *self, NMDevice *device) state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); if (priv->pending_ip4_config || _state_is_active (state)) - return nm_system_device_is_up (device); + return nm_system_iface_is_up (nm_device_get_ip_ifindex (device)); } return TRUE; @@ -792,7 +792,7 @@ nm_modem_hw_bring_up (NMModem *self, NMDevice *device, gboolean *no_firmware) state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device)); if (priv->pending_ip4_config || _state_is_active (state)) - return nm_system_device_set_up_down (device, TRUE, no_firmware); + return nm_system_iface_set_up (nm_device_get_ip_ifindex (device), TRUE, no_firmware); } return TRUE; diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index 35b73670..8556c5bd 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -59,6 +59,7 @@ #include "nm-logging.h" #include "nm-properties-changed-signal.h" #include "nm-dhcp-manager.h" +#include "nm-netlink-utils.h" #include "nm-device-ethernet-glue.h" @@ -546,19 +547,19 @@ real_take_down (NMDevice *dev) static gboolean real_hw_is_up (NMDevice *device) { - return nm_system_device_is_up (device); + return nm_system_iface_is_up (nm_device_get_ip_ifindex (device)); } static gboolean real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) { - return nm_system_device_set_up_down (dev, TRUE, no_firmware); + return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware); } static void real_hw_take_down (NMDevice *dev) { - nm_system_device_set_up_down (dev, FALSE, NULL); + nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL); } NMDevice * @@ -677,7 +678,7 @@ _set_hw_addr (NMDeviceEthernet *self, const guint8 *addr, const char *detail) /* Can't change MAC address while device is up */ real_hw_take_down (dev); - success = nm_system_device_set_mac (iface, (struct ether_addr *) addr); + success = nm_system_iface_set_mac (nm_device_get_ip_ifindex (dev), (struct ether_addr *) addr); if (success) { /* MAC address succesfully changed; update the current MAC to match */ _update_hw_addr (self, addr); @@ -1796,73 +1797,19 @@ wired_match_config (NMDevice *self, NMConnection *connection) return TRUE; } -typedef struct { - int ifindex; - NMIP4Address *addr; - gboolean found; -} AddrData; - -static void -check_one_address (struct nl_object *object, void *user_data) -{ - AddrData *data = user_data; - struct rtnl_addr *addr = (struct rtnl_addr *) object; - struct nl_addr *local; - struct in_addr tmp; - - if (rtnl_addr_get_ifindex (addr) != data->ifindex) - return; - if (rtnl_addr_get_family (addr) != AF_INET) - return; - - if (nm_ip4_address_get_prefix (data->addr) != rtnl_addr_get_prefixlen (addr)) - return; - - local = rtnl_addr_get_local (addr); - if (nl_addr_get_family (local) != AF_INET) - return; - if (nl_addr_get_len (local) != sizeof (struct in_addr)) - return; - if (!nl_addr_get_binary_addr (local)) - return; - - memcpy (&tmp, nl_addr_get_binary_addr (local), nl_addr_get_len (local)); - if (tmp.s_addr != nm_ip4_address_get_address (data->addr)) - return; - - /* Yay, found it */ - data->found = TRUE; -} - static gboolean ip4_match_config (NMDevice *self, NMConnection *connection) { NMSettingIP4Config *s_ip4; - struct nl_handle *nlh = NULL; - struct nl_cache *addr_cache = NULL; int i, num; GSList *leases, *iter; NMDHCPManager *dhcp_mgr; const char *method; - int ifindex; - AddrData check_data; - - ifindex = nm_device_get_ifindex (self); - s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); + s_ip4 = nm_connection_get_setting_ip4_config (connection); if (!s_ip4) return FALSE; - /* Read all the device's IP addresses */ - nlh = nm_netlink_get_default_handle (); - if (!nlh) - return FALSE; - - addr_cache = rtnl_addr_alloc_cache (nlh); - if (!addr_cache) - return FALSE; - nl_cache_mngt_provide (addr_cache); - /* Get any saved leases that apply to this connection */ dhcp_mgr = nm_dhcp_manager_get (); leases = nm_dhcp_manager_get_lease_config (dhcp_mgr, @@ -1876,15 +1823,14 @@ ip4_match_config (NMDevice *self, NMConnection *connection) /* Find at least one lease's address on the device */ for (iter = leases; iter; iter = g_slist_next (iter)) { - NMIP4Config *addr = iter->data; - - memset (&check_data, 0, sizeof (check_data)); - check_data.ifindex = ifindex; - check_data.found = FALSE; - check_data.addr = nm_ip4_config_get_address (addr, 0); - - nl_cache_foreach (addr_cache, check_one_address, &check_data); - if (check_data.found) { + NMIP4Config *ip4_config = iter->data; + NMIP4Address *addr = nm_ip4_config_get_address (ip4_config, 0); + struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) }; + + if (addr && nm_netlink_find_address (nm_device_get_ip_ifindex (self), + AF_INET, + &tmp, + nm_ip4_address_get_prefix (addr))) { found = TRUE; /* Yay, device has same address as a lease */ break; } @@ -1908,16 +1854,16 @@ ip4_match_config (NMDevice *self, NMConnection *connection) /* Everything below for static addressing */ - /* Find all IP4 addresses of this connection in the device's address list */ + /* Find all IP4 addresses of this connection on the device */ num = nm_setting_ip4_config_get_num_addresses (s_ip4); for (i = 0; i < num; i++) { - memset (&check_data, 0, sizeof (check_data)); - check_data.ifindex = ifindex; - check_data.found = FALSE; - check_data.addr = nm_setting_ip4_config_get_address (s_ip4, i); + NMIP4Address *addr = nm_setting_ip4_config_get_address (s_ip4, i); + struct in_addr tmp = { .s_addr = nm_ip4_address_get_address (addr) }; - nl_cache_foreach (addr_cache, check_one_address, &check_data); - if (!check_data.found) + if (!nm_netlink_find_address (nm_device_get_ip_ifindex (self), + AF_INET, + &tmp, + nm_ip4_address_get_prefix (addr))) return FALSE; } diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c index 88322344..ae14279b 100644 --- a/src/nm-device-olpc-mesh.c +++ b/src/nm-device-olpc-mesh.c @@ -271,19 +271,19 @@ error: static gboolean real_hw_is_up (NMDevice *device) { - return nm_system_device_is_up (device); + return nm_system_iface_is_up (nm_device_get_ip_ifindex (device)); } static gboolean real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) { - return nm_system_device_set_up_down (dev, TRUE, no_firmware); + return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware); } static void real_hw_take_down (NMDevice *dev) { - nm_system_device_set_up_down (dev, FALSE, NULL); + nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL); } static gboolean diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 278d9a06..6fac0d03 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -1133,7 +1133,7 @@ out: static gboolean real_hw_is_up (NMDevice *device) { - return nm_system_device_is_up (device); + return nm_system_iface_is_up (nm_device_get_ip_ifindex (device)); } static gboolean @@ -1142,13 +1142,13 @@ real_hw_bring_up (NMDevice *device, gboolean *no_firmware) if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled) return FALSE; - return nm_system_device_set_up_down (device, TRUE, no_firmware); + return nm_system_iface_set_up (nm_device_get_ip_ifindex (device), TRUE, no_firmware); } static void -real_hw_take_down (NMDevice *dev) +real_hw_take_down (NMDevice *device) { - nm_system_device_set_up_down (dev, FALSE, NULL); + nm_system_iface_set_up (nm_device_get_ip_ifindex (device), FALSE, NULL); } static gboolean @@ -1209,7 +1209,7 @@ _set_hw_addr (NMDeviceWifi *self, const guint8 *addr, const char *detail) /* Can't change MAC address while device is up */ real_hw_take_down (dev); - success = nm_system_device_set_mac (iface, (struct ether_addr *) addr); + success = nm_system_iface_set_mac (nm_device_get_ip_ifindex (dev), (struct ether_addr *) addr); if (success) { /* MAC address succesfully changed; update the current MAC to match */ _update_hw_addr (self, addr); diff --git a/src/nm-device.c b/src/nm-device.c index 1301197a..d570d1bd 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -47,6 +47,8 @@ #include "nm-utils.h" #include "nm-logging.h" #include "nm-netlink-monitor.h" +#include "nm-netlink-utils.h" +#include "nm-netlink-compat.h" #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" #include "nm-setting-connection.h" @@ -187,6 +189,8 @@ static void addrconf6_cleanup (NMDevice *self); static void dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release); static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release); +static const char *reason_to_string (NMDeviceStateReason reason); + static void device_interface_init (NMDeviceInterface *device_interface_class) @@ -1591,16 +1595,15 @@ real_act_stage3_ip4_config_start (NMDevice *self, NMDeviceStateReason *reason) NMSettingIP4Config *s_ip4; NMActRequest *req; NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; - const char *ip_iface, *method = NULL; + const char *method = NULL; + int ifindex; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - /* Use the IP interface (not the control interface) for IP stuff */ - ip_iface = nm_device_get_ip_iface (self); - /* Make sure the interface is up before trying to do anything with it */ - if (!nm_system_device_is_up_with_iface (ip_iface)) - nm_system_device_set_up_down_with_iface (ip_iface, TRUE, NULL); + ifindex = nm_device_get_ip_ifindex (self); + if (!nm_system_iface_is_up (ifindex)) + nm_system_iface_set_up (ifindex, TRUE, NULL); req = nm_device_get_act_request (self); connection = nm_act_request_get_connection (req); @@ -1680,10 +1683,10 @@ dhcp6_start (NMDevice *self, */ err = nm_system_set_ip6_route (priv->ip_iface ? priv->ip_ifindex : priv->ifindex, &dest, 8, NULL, 256, 0, RTPROT_BOOT, RT_TABLE_LOCAL, NULL); - if (err && (nl_get_errno () != EEXIST)) { + if (err && (err != -NLE_EXIST)) { nm_log_err (LOGD_DEVICE | LOGD_IP6, "(%s): failed to add IPv6 multicast route: %s", - priv->ip_iface ? priv->ip_iface : priv->iface, nl_geterror ()); + priv->ip_iface ? priv->ip_iface : priv->iface, nl_geterror (err)); } s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); @@ -2522,7 +2525,7 @@ start_sharing (NMDevice *self) add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface); add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface); add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface); - add_share_rule (req, "nat", "POSTROUTING --source %s/%s --destination ! %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask); + add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask); nm_act_request_set_shared (req, TRUE); @@ -2820,11 +2823,12 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; gboolean tried_ipv6 = FALSE; + int ifindex, family; g_return_if_fail (self != NULL); - nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason: %d).", - nm_device_get_iface (self), reason); + nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason '%s') [%d]", + nm_device_get_iface (self), reason_to_string (reason), reason); /* Save whether or not we tried IPv6 for later */ if (NM_DEVICE_GET_PRIVATE (self)->ip6_manager) @@ -2857,8 +2861,10 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason) clear_act_request (self); /* Take out any entries in the routing table and any IP address the device had. */ - nm_system_device_flush_routes (self, tried_ipv6 ? AF_UNSPEC : AF_INET); - nm_system_device_flush_addresses (self, tried_ipv6 ? AF_UNSPEC : AF_INET); + ifindex = nm_device_get_ip_ifindex (self); + family = tried_ipv6 ? AF_UNSPEC : AF_INET; + nm_system_iface_flush_routes (ifindex, family); + nm_system_iface_flush_addresses (ifindex, family); nm_device_update_ip4_address (self); /* Clean up nameservers and addresses */ @@ -3009,6 +3015,7 @@ nm_device_set_ip4_config (NMDevice *self, gboolean success = TRUE; NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; NMDnsManager *dns_mgr; + int ip_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); g_return_val_if_fail (reason != NULL, FALSE); @@ -3039,8 +3046,10 @@ nm_device_set_ip4_config (NMDevice *self, /* Don't touch the device's actual IP config if the connection is * assumed when NM starts. */ - if (!assumed) - success = nm_system_apply_ip4_config (ip_iface, new_config, nm_device_get_priority (self), diff); + if (!assumed) { + ip_ifindex = nm_device_get_ip_ifindex (self); + success = nm_system_apply_ip4_config (ip_ifindex, new_config, nm_device_get_priority (self), diff); + } if (success || assumed) { /* Export over D-Bus */ @@ -3112,12 +3121,14 @@ nm_device_set_ip6_config (NMDevice *self, gboolean success = TRUE; NMIP6ConfigCompareFlags diff = NM_IP6_COMPARE_FLAG_ALL; NMDnsManager *dns_mgr; + int ip_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); g_return_val_if_fail (reason != NULL, FALSE); priv = NM_DEVICE_GET_PRIVATE (self); ip_iface = nm_device_get_ip_iface (self); + ip_ifindex = nm_device_get_ip_ifindex (self); old_config = priv->ip6_config; @@ -3143,7 +3154,7 @@ nm_device_set_ip6_config (NMDevice *self, * assumed when NM starts. */ if (!assumed) - success = nm_system_apply_ip6_config (ip_iface, new_config, nm_device_get_priority (self), diff); + success = nm_system_apply_ip6_config (ip_ifindex, new_config, nm_device_get_priority (self), diff); if (success || assumed) { /* Export over D-Bus */ @@ -3395,7 +3406,7 @@ set_property (GObject *object, guint prop_id, priv->iface = g_value_dup_string (value); if (priv->iface) { priv->ifindex = nm_netlink_iface_to_index (priv->iface); - if (priv->ifindex < 0) { + if (priv->ifindex <= 0) { nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", priv->iface); } } diff --git a/src/nm-manager.c b/src/nm-manager.c index f5782254..9200f348 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -214,7 +214,8 @@ typedef struct { gboolean net_enabled; NMVPNManager *vpn_manager; - guint vpn_manager_id; + gulong vpn_manager_activated_id; + gulong vpn_manager_deactivated_id; NMModemManager *modem_manager; guint modem_added_id; @@ -377,6 +378,18 @@ manager_sleeping (NMManager *self) } static void +vpn_manager_connection_activated_cb (NMVPNManager *manager, + NMVPNConnection *vpn, + NMVPNConnectionState state, + NMVPNConnectionStateReason reason, + gpointer user_data) +{ + /* Update timestamp for the VPN connection */ + nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (nm_vpn_connection_get_connection (vpn)), + (guint64) time (NULL)); +} + +static void vpn_manager_connection_deactivated_cb (NMVPNManager *manager, NMVPNConnection *vpn, NMVPNConnectionState state, @@ -3159,9 +3172,13 @@ dispose (GObject *object) g_object_unref (priv->settings); - if (priv->vpn_manager_id) { - g_source_remove (priv->vpn_manager_id); - priv->vpn_manager_id = 0; + if (priv->vpn_manager_activated_id) { + g_source_remove (priv->vpn_manager_activated_id); + priv->vpn_manager_activated_id = 0; + } + if (priv->vpn_manager_deactivated_id) { + g_source_remove (priv->vpn_manager_deactivated_id); + priv->vpn_manager_deactivated_id = 0; } g_object_unref (priv->vpn_manager); @@ -3402,6 +3419,7 @@ static gboolean periodic_update_active_connection_timestamps (gpointer user_data) { NMManager *manager = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); GPtrArray *active; int i; @@ -3416,6 +3434,15 @@ periodic_update_active_connection_timestamps (gpointer user_data) if (device && nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (nm_act_request_get_connection (req)), (guint64) time (NULL)); + else { + /* The connection is probably VPN */ + NMVPNConnection *vpn_con; + + vpn_con = nm_vpn_manager_get_vpn_connection_for_active (priv->vpn_manager, active_path); + if (vpn_con && nm_vpn_connection_get_vpn_state (vpn_con) == NM_VPN_CONNECTION_STATE_ACTIVATED) + nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (nm_vpn_connection_get_connection (vpn_con)), + (guint64) time (NULL)); + } } return TRUE; @@ -3426,7 +3453,7 @@ nm_manager_init (NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); DBusGConnection *g_connection; - guint id, i; + guint i; GFile *file; /* Initialize rfkill structures and states */ @@ -3471,9 +3498,10 @@ nm_manager_init (NMManager *manager) G_CALLBACK (modem_removed), manager); priv->vpn_manager = nm_vpn_manager_get (); - id = g_signal_connect (G_OBJECT (priv->vpn_manager), "connection-deactivated", - G_CALLBACK (vpn_manager_connection_deactivated_cb), manager); - priv->vpn_manager_id = id; + priv->vpn_manager_activated_id = g_signal_connect (G_OBJECT (priv->vpn_manager), "connection-activated", + G_CALLBACK (vpn_manager_connection_activated_cb), manager); + priv->vpn_manager_deactivated_id = g_signal_connect (G_OBJECT (priv->vpn_manager), "connection-deactivated", + G_CALLBACK (vpn_manager_connection_deactivated_cb), manager); g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); diff --git a/src/nm-netlink-compat.c b/src/nm-netlink-compat.c new file mode 100644 index 00000000..e91a1ff2 --- /dev/null +++ b/src/nm-netlink-compat.c @@ -0,0 +1,105 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Caixa Magica Software. + */ + +#include <config.h> +#include <glib.h> + +#include "nm-netlink-compat.h" + +#ifndef HAVE_LIBNL1 +struct rtnl_nexthop * +nm_netlink_get_nh (struct rtnl_route * route) +{ + int hops; + + hops = rtnl_route_get_nnexthops (route); + g_return_val_if_fail(hops > 0, NULL); + return rtnl_route_nexthop_n (route, 0); +} + +int +rtnl_route_get_oif (struct rtnl_route * route) +{ + struct rtnl_nexthop * nh; + + nh = nm_netlink_get_nh(route); + g_return_val_if_fail(nh, -NLE_OBJ_NOTFOUND); + return rtnl_route_nh_get_ifindex (nh); +} + +int +rtnl_route_set_oif (struct rtnl_route * route, int ifindex) +{ + struct rtnl_nexthop * nh; + + nh = rtnl_route_nh_alloc(); + rtnl_route_nh_set_ifindex(nh, ifindex); + rtnl_route_add_nexthop(route, nh); + return 0; +} + +struct nl_addr * +rtnl_route_get_gateway (struct rtnl_route * route) +{ + struct rtnl_nexthop * nh; + + nh = nm_netlink_get_nh(route); + g_return_val_if_fail(nh, NULL); + return rtnl_route_nh_get_gateway(nh); +} + +int +rtnl_route_set_gateway (struct rtnl_route * route, struct nl_addr * gw_addr) +{ + struct rtnl_nexthop * nh; + + nh = nm_netlink_get_nh(route); + g_return_val_if_fail(nh, -NLE_OBJ_NOTFOUND); + + rtnl_route_nh_set_gateway(nh, gw_addr); + return 0; +} + +int +rtnl_route_get_dst_len(struct rtnl_route * rtnlroute) +{ + struct nl_addr * dst; + + dst = rtnl_route_get_dst(rtnlroute); + return nl_addr_get_prefixlen(dst); +} +#endif + +#ifdef HAVE_LIBNL1 +int +nl_compat_error (int err) +{ + err = abs (err); + + if (err == EEXIST) + err = NLE_EXIST; + else if (err == ENOENT || err == ESRCH) + err = NLE_OBJ_NOTFOUND; + else if (err == ERANGE) + err = NLE_RANGE; + + return -err; +} +#endif diff --git a/src/nm-netlink-compat.h b/src/nm-netlink-compat.h new file mode 100644 index 00000000..f6225c70 --- /dev/null +++ b/src/nm-netlink-compat.h @@ -0,0 +1,198 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Caixa Magica Software. + */ + +#ifndef NM_NETLINK_COMPAT_H +#define NM_NETLINK_COMPAT_H + +#include <errno.h> + +#include <netlink/netlink.h> +#include <netlink/route/rtnl.h> +#include <netlink/route/link.h> +#include <netlink/route/route.h> +#include <netlink/route/addr.h> + + +#include <netlink/netlink.h> +#include <netlink/cache.h> +#include <netlink/utils.h> +#include <netlink/data.h> +#include <netlink/route/rtnl.h> +#include <netlink/route/route.h> +#include <netlink/route/link.h> +#include <netlink/route/nexthop.h> + +#include <config.h> + +/* libnl-1 API compatibility for libnl-2/3*/ +#ifndef HAVE_LIBNL1 + +struct rtnl_nexthop * nm_netlink_get_nh(struct rtnl_route *); +int rtnl_route_get_oif(struct rtnl_route *); +int rtnl_route_set_oif(struct rtnl_route *, int); +int rtnl_route_set_gateway(struct rtnl_route *, struct nl_addr *); +int rtnl_route_get_dst_len(struct rtnl_route *); +struct nl_addr * rtnl_route_get_gateway(struct rtnl_route *); +#endif + +/* libnl-2 API compatibility for libnl-3 */ +#ifdef HAVE_LIBNL3 +static inline int +__rtnl_link_alloc_cache (struct nl_sock *h, struct nl_cache **cache) +{ + return rtnl_link_alloc_cache (h, AF_UNSPEC, cache); +} +#define rtnl_link_alloc_cache __rtnl_link_alloc_cache +#endif + +/* libnl-1.0 compat functions */ +#ifdef HAVE_LIBNL1 + +#define nl_sock nl_handle + +/* libnl-1.0 functions with similar prototypes */ +#define nl_socket_alloc nl_handle_alloc +#define nl_socket_alloc_cb nl_handle_alloc_cb +#define nl_socket_free nl_handle_destroy +#define nl_socket_set_passcred nl_set_passcred +#define nl_socket_disable_seq_check nl_disable_sequence_check +#define rtnl_route_set_priority rtnl_route_set_prio +#define nlmsg_datalen nlmsg_len + +/* auxiliary functions */ +int nl_compat_error (int); + +/* libnl-1.0 functions with modified prototypes in libnl-2/3*/ +static inline const char * +__nl_geterror (int err) +{ + /* err is set, can be parsed */ + return nl_geterror (); +} +#define nl_geterror __nl_geterror + +static inline int +__rtnl_addr_alloc_cache (struct nl_sock *h, struct nl_cache **cache) +{ + g_return_val_if_fail (cache != NULL, -EINVAL); + + *cache = rtnl_addr_alloc_cache (h); + return *cache ? 0 : -ENOMEM; +} +#define rtnl_addr_alloc_cache __rtnl_addr_alloc_cache + +static inline int +__rtnl_route_alloc_cache (struct nl_sock *h, int family, int flags, struct nl_cache **cache) +{ + g_return_val_if_fail (cache != NULL, -EINVAL); + + *cache = rtnl_route_alloc_cache (h); + return *cache ? 0 : -ENOMEM; +} +#define rtnl_route_alloc_cache __rtnl_route_alloc_cache + +static inline int +__rtnl_link_alloc_cache (struct nl_sock *h, struct nl_cache **cache) +{ + g_return_val_if_fail (cache != NULL, -EINVAL); + + *cache = rtnl_link_alloc_cache (h); + return *cache ? 0 : -ENOMEM; +} +#define rtnl_link_alloc_cache __rtnl_link_alloc_cache + +static inline int +__rtnl_route_get_metric (struct rtnl_route *route, int metric, unsigned int *value) +{ + g_return_val_if_fail (value != NULL, -EINVAL); + + *value = rtnl_route_get_metric (route, metric); + return 0; +} +#define rtnl_route_get_metric __rtnl_route_get_metric + +static inline int +__rtnl_addr_add (struct nl_sock *h, struct rtnl_addr *addr, int flags) +{ + return nl_compat_error (rtnl_addr_add (h, addr, flags)); +} +#define rtnl_addr_add __rtnl_addr_add + +static inline int +__rtnl_route_add (struct nl_sock *sk, struct rtnl_route *route, int flags) +{ + return nl_compat_error (rtnl_route_add (sk, route, flags)); +} +#define rtnl_route_add __rtnl_route_add + +static inline int +rtnl_route_delete (struct nl_sock *h, struct rtnl_route *route, int flags) +{ + return nl_compat_error (rtnl_route_del (h, route, flags)); +} +#define rtnl_route_del rtnl_route_delete + +static inline int +__rtnl_link_change (struct nl_sock *h, struct rtnl_link *old, struct rtnl_link *tmpl, int flags) +{ + return nl_compat_error (rtnl_link_change (h, old, tmpl,flags)); +} +#define rtnl_link_change __rtnl_link_change + +static inline int +__nl_cache_include (struct nl_cache *cache, struct nl_object *obj, change_func_t cb, void *data) +{ + return nl_cache_include (cache, obj, cb); +} +#define nl_cache_include __nl_cache_include + +#define NLE_SUCCESS 0 +#define NLE_FAILURE 1 +#define NLE_INTR 2 +#define NLE_BAD_SOCK 3 +#define NLE_AGAIN 4 +#define NLE_NOMEM 5 +#define NLE_EXIST 6 +#define NLE_INVAL 7 +#define NLE_RANGE 8 +#define NLE_MSGSIZE 9 +#define NLE_OPNOTSUPP 10 +#define NLE_AF_NOSUPPORT 11 +#define NLE_OBJ_NOTFOUND 12 +#define NLE_NOATTR 13 +#define NLE_MISSING_ATTR 14 +#define NLE_AF_MISMATCH 15 +#define NLE_SEQ_MISMATCH 16 +#define NLE_MSG_OVERFLOW 17 +#define NLE_MSG_TRUNC 18 +#define NLE_NOADDR 19 +#define NLE_SRCRT_NOSUPPORT 20 +#define NLE_MSG_TOOSHORT 21 +#define NLE_MSGTYPE_NOSUPPORT 22 +#define NLE_OBJ_MISMATCH 23 +#define NLE_NOCACHE 24 +#define NLE_BUSY 25 +#define NLE_PROTO_MISMATCH 26 +#define NLE_NOACCESS 27 +#define NLE_PERM 28 +#define NLE_PKTLOC_FILE 29 +#endif + +#endif /* NM_NETLINK_COMPAT_H */ diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c index 13b3ab98..fb859814 100644 --- a/src/nm-netlink-monitor.c +++ b/src/nm-netlink-monitor.c @@ -45,6 +45,7 @@ #include <glib.h> #include <glib/gi18n.h> +#include "nm-netlink-compat.h" #include "nm-netlink-monitor.h" #include "nm-logging.h" @@ -58,12 +59,12 @@ typedef struct { /* Async event listener connection */ - struct nl_handle *nlh_event; + struct nl_sock *nlh_event; GIOChannel * io_channel; guint event_id; /* Sync/blocking request/response connection */ - struct nl_handle *nlh_sync; + struct nl_sock *nlh_sync; struct nl_cache * link_cache; guint request_status_id; @@ -98,7 +99,7 @@ link_msg_handler (struct nl_object *obj, void *arg) error = g_error_new (NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, _("error processing netlink message: %s"), - nl_geterror ()); + nl_geterror (ENOMEM)); g_signal_emit (self, signals[ERROR], 0, error); g_error_free (error); return; @@ -130,7 +131,7 @@ link_msg_handler (struct nl_object *obj, void *arg) static int event_msg_recv (struct nl_msg *msg, void *arg) { - struct nl_handle *nlh = arg; + struct nl_sock *nlh = arg; struct nlmsghdr *hdr = nlmsg_hdr (msg); struct ucred *creds = nlmsg_get_creds (msg); const struct sockaddr_nl *snl; @@ -195,6 +196,7 @@ event_handler (GIOChannel *channel, NMNetlinkMonitor *self = (NMNetlinkMonitor *) user_data; NMNetlinkMonitorPrivate *priv; GError *error = NULL; + int err; g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), TRUE); @@ -225,11 +227,12 @@ event_handler (GIOChannel *channel, g_return_val_if_fail (!(io_condition & ~EVENT_CONDITIONS), FALSE); /* Process the netlink messages */ - if (nl_recvmsgs_default (priv->nlh_event) < 0) { + err = nl_recvmsgs_default (priv->nlh_event); + if (err < 0) { error = g_error_new (NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, _("error processing netlink message: %s"), - nl_geterror ()); + nl_geterror (err)); g_signal_emit (self, signals[ERROR], 0, error); g_error_free (error); } @@ -238,32 +241,35 @@ event_handler (GIOChannel *channel, } static gboolean -nlh_setup (struct nl_handle *nlh, +nlh_setup (struct nl_sock *nlh, nl_recvmsg_msg_cb_t valid_func, gpointer cb_data, GError **error) { + int err; + nl_socket_modify_cb (nlh, NL_CB_MSG_IN, NL_CB_CUSTOM, event_msg_recv, cb_data); if (valid_func) nl_socket_modify_cb (nlh, NL_CB_VALID, NL_CB_CUSTOM, valid_func, cb_data); - if (nl_connect (nlh, NETLINK_ROUTE) < 0) { + err = nl_connect (nlh, NETLINK_ROUTE); + if (err < 0) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, _("unable to connect to netlink for monitoring link status: %s"), - nl_geterror ()); + nl_geterror (err)); return FALSE; } /* Enable unix socket peer credentials which we use for verifying that the * sender of the message is actually the kernel. */ - if (nl_set_passcred (nlh, 1) < 0) { + if (nl_socket_set_passcred (nlh, 1) < 0) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_CONNECT, _("unable to enable netlink handle credential passing: %s"), - nl_geterror ()); + nl_geterror (err)); return FALSE; } @@ -276,27 +282,24 @@ event_connection_setup (NMNetlinkMonitor *self, GError **error) NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); GError *channel_error = NULL; GIOFlags channel_flags; - struct nl_cb *cb; int fd; g_return_val_if_fail (priv->io_channel == NULL, FALSE); /* Set up the event listener connection */ - cb = nl_cb_alloc (NL_CB_DEFAULT); - priv->nlh_event = nl_handle_alloc_cb (cb); - nl_cb_put (cb); + priv->nlh_event = nl_socket_alloc (); if (!priv->nlh_event) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, _("unable to allocate netlink handle for monitoring link status: %s"), - nl_geterror ()); + nl_geterror (ENOMEM)); goto error; } if (!nlh_setup (priv->nlh_event, event_msg_ready, self, error)) goto error; - nl_disable_sequence_check (priv->nlh_event); + nl_socket_disable_seq_check (priv->nlh_event); /* Subscribe to the LINK group for internal carrier signals */ if (!nm_netlink_monitor_subscribe (self, RTNLGRP_LINK, error)) @@ -327,7 +330,7 @@ error: nm_netlink_monitor_close_connection (self); if (priv->nlh_event) { - nl_handle_destroy (priv->nlh_event); + nl_socket_free (priv->nlh_event); priv->nlh_event = NULL; } @@ -338,20 +341,18 @@ static gboolean sync_connection_setup (NMNetlinkMonitor *self, GError **error) { NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); - struct nl_cb *cb; #ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND struct nl_cache *addr_cache; #endif + int err; /* Set up the event listener connection */ - cb = nl_cb_alloc (NL_CB_DEFAULT); - priv->nlh_sync = nl_handle_alloc_cb (cb); - nl_cb_put (cb); + priv->nlh_sync = nl_socket_alloc (); if (!priv->nlh_sync) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_HANDLE, _("unable to allocate netlink handle for monitoring link status: %s"), - nl_geterror ()); + nl_geterror (ENOMEM)); goto error; } @@ -365,16 +366,18 @@ sync_connection_setup (NMNetlinkMonitor *self, GError **error) * result, most addresses will not compare as equal even to * themselves, busting caching. */ - addr_cache = rtnl_addr_alloc_cache (priv->nlh_sync); + rtnl_addr_alloc_cache (priv->nlh_sync, &addr_cache); + g_warn_if_fail (addr_cache != NULL); nl_cache_get_ops (addr_cache)->co_obj_ops->oo_id_attrs &= ~0x80; nl_cache_free (addr_cache); #endif - if ((priv->link_cache = rtnl_link_alloc_cache (priv->nlh_sync)) == NULL) { + err = rtnl_link_alloc_cache (priv->nlh_sync, &priv->link_cache); + if (err < 0) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_ALLOC_LINK_CACHE, _("unable to allocate netlink link cache for monitoring link status: %s"), - nl_geterror ()); + nl_geterror (err)); goto error; } nl_cache_mngt_provide (priv->link_cache); @@ -388,7 +391,7 @@ error: } if (priv->nlh_sync) { - nl_handle_destroy (priv->nlh_sync); + nl_socket_free (priv->nlh_sync); priv->nlh_sync = NULL; } @@ -483,7 +486,7 @@ gboolean nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error) { NMNetlinkMonitorPrivate *priv; - int subs; + int subs, err; g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); @@ -496,11 +499,12 @@ nm_netlink_monitor_subscribe (NMNetlinkMonitor *self, int group, GError **error) subs = get_subs (self, group) + 1; if (subs == 1) { - if (nl_socket_add_membership (priv->nlh_event, group) < 0) { + err = nl_socket_add_membership (priv->nlh_event, group); + if (err < 0) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_NETLINK_JOIN_GROUP, _("unable to join netlink group: %s"), - nl_geterror ()); + nl_geterror (err)); return FALSE; } } @@ -558,15 +562,17 @@ deferred_emit_carrier_state (gpointer user_data) { NMNetlinkMonitor *self = NM_NETLINK_MONITOR (user_data); NMNetlinkMonitorPrivate *priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); + int err; priv->request_status_id = 0; /* Update the link cache with latest state, and if there are no errors * emit the link states for all the interfaces in the cache. */ - if (nl_cache_refill (priv->nlh_sync, priv->link_cache)) { - nm_log_err (LOGD_HW, "error updating link cache: %s", nl_geterror ()); - } else + err = nl_cache_refill (priv->nlh_sync, priv->link_cache); + if (err < 0) + nm_log_err (LOGD_HW, "error updating link cache: %s", nl_geterror (err)); + else nl_cache_foreach_filter (priv->link_cache, NULL, link_msg_handler, self); return FALSE; @@ -614,6 +620,7 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self, NMNetlinkMonitorPrivate *priv; GetFlagsInfo info; struct rtnl_link *filter; + int err; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); @@ -622,12 +629,13 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self, priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); /* Update the link cache with the latest information */ - if (nl_cache_refill (priv->nlh_sync, priv->link_cache)) { + err = nl_cache_refill (priv->nlh_sync, priv->link_cache); + if (err < 0) { g_set_error (error, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, _("error updating link cache: %s"), - nl_geterror ()); + nl_geterror (err)); return FALSE; } @@ -640,7 +648,7 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_LINK_CACHE_UPDATE, _("error updating link cache: %s"), - nl_geterror ()); + nl_geterror (err)); return FALSE; } @@ -651,7 +659,7 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self, NM_NETLINK_MONITOR_ERROR, NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, _("error processing netlink message: %s"), - nl_geterror ()); + nl_geterror (err)); return FALSE; } rtnl_link_set_ifindex (filter, ifindex); @@ -678,11 +686,11 @@ nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *self, /***************************************************************/ -struct nl_handle * +struct nl_sock * nm_netlink_get_default_handle (void) { NMNetlinkMonitor *self; - struct nl_handle *nlh; + struct nl_sock *nlh; self = nm_netlink_monitor_get (); nlh = NM_NETLINK_MONITOR_GET_PRIVATE (self)->nlh_sync; @@ -796,12 +804,12 @@ finalize (GObject *object) } if (priv->nlh_event) { - nl_handle_destroy (priv->nlh_event); + nl_socket_free (priv->nlh_event); priv->nlh_event = NULL; } if (priv->nlh_sync) { - nl_handle_destroy (priv->nlh_sync); + nl_socket_free (priv->nlh_sync); priv->nlh_sync = NULL; } diff --git a/src/nm-netlink-monitor.h b/src/nm-netlink-monitor.h index 8b57a312..5c1fa339 100644 --- a/src/nm-netlink-monitor.h +++ b/src/nm-netlink-monitor.h @@ -90,10 +90,12 @@ gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor guint32 *ifflags, GError **error); +#include "nm-netlink-compat.h" + /* Generic utility functions */ int nm_netlink_iface_to_index (const char *iface); char * nm_netlink_index_to_iface (int idx); struct rtnl_link *nm_netlink_index_to_rtnl_link (int idx); -struct nl_handle *nm_netlink_get_default_handle (void); +struct nl_sock * nm_netlink_get_default_handle (void); #endif /* NM_NETLINK_MONITOR_H */ diff --git a/src/nm-netlink-utils.c b/src/nm-netlink-utils.c new file mode 100644 index 00000000..743f9465 --- /dev/null +++ b/src/nm-netlink-utils.c @@ -0,0 +1,423 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + */ + +#include "logging/nm-logging.h" +#include "nm-netlink-utils.h" +#include "nm-netlink-monitor.h" +#include "nm-netlink-compat.h" + +#include <arpa/inet.h> +#include <netinet/in.h> +#include <netlink/netlink.h> +#include <netlink/addr.h> +#include <netlink/route/addr.h> + +#include <errno.h> + +typedef struct { + int ifindex; + int family; + void *addr; + int addrlen; + int prefix; + gboolean found; +} FindAddrInfo; + +static void +find_one_address (struct nl_object *object, void *user_data) +{ + FindAddrInfo *info = user_data; + struct rtnl_addr *addr = (struct rtnl_addr *) object; + struct nl_addr *local; + void *binaddr; + + if (info->found) + return; + + if (rtnl_addr_get_ifindex (addr) != info->ifindex) + return; + if (rtnl_addr_get_family (addr) != info->family) + return; + + if (rtnl_addr_get_prefixlen (addr) != info->prefix) + return; + + local = rtnl_addr_get_local (addr); + if (nl_addr_get_family (local) != info->family) + return; + if (nl_addr_get_len (local) != info->addrlen) + return; + binaddr = nl_addr_get_binary_addr (local); + if (binaddr) { + if (memcmp (binaddr, info->addr, info->addrlen) == 0) + info->found = TRUE; /* Yay, found it */ + } +} + +/** + * nm_netlink_find_address: + * @ifindex: interface index + * @family: address family, either AF_INET or AF_INET6 + * @addr: binary address, either struct in_addr* or struct in6_addr* + * @prefix: prefix length + * + * Searches for a matching address on the given interface. + * + * Returns: %TRUE if the given address was found on the interface, %FALSE if it + * was not found or an error occurred. + **/ +gboolean +nm_netlink_find_address (int ifindex, + int family, + void *addr, /* struct in_addr or struct in6_addr */ + int prefix) +{ + struct nl_sock *nlh = NULL; + struct nl_cache *cache = NULL; + FindAddrInfo info; + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + g_return_val_if_fail (addr != NULL, FALSE); + g_return_val_if_fail (prefix >= 0, FALSE); + + memset (&info, 0, sizeof (info)); + info.ifindex = ifindex; + info.family = family; + info.prefix = prefix; + info.addr = addr; + if (family == AF_INET) + info.addrlen = sizeof (struct in_addr); + else if (family == AF_INET6) + info.addrlen = sizeof (struct in6_addr); + else + g_assert_not_reached (); + + nlh = nm_netlink_get_default_handle (); + if (nlh) { + rtnl_addr_alloc_cache(nlh, &cache); + if (cache) { + nl_cache_mngt_provide (cache); + nl_cache_foreach (cache, find_one_address, &info); + nl_cache_free (cache); + } + } + return info.found; +} + +struct rtnl_route * +nm_netlink_route_new (int ifindex, + int family, + int mss, + ...) +{ + va_list var_args; + struct rtnl_route *route; + NmNlProp prop = NMNL_PROP_INVALID; + int value; + + route = rtnl_route_alloc (); + g_return_val_if_fail (route != NULL, NULL); + + if (ifindex >= 0) + rtnl_route_set_oif (route, ifindex); + if (family != AF_UNSPEC) + rtnl_route_set_family (route, family); + if (mss > 0) + rtnl_route_set_metric (route, RTAX_ADVMSS, mss); + + va_start (var_args, mss); + prop = va_arg (var_args, NmNlProp); + while (prop != NMNL_PROP_INVALID) { + value = va_arg (var_args, int); + + if (prop == NMNL_PROP_PROT && value != RTPROT_UNSPEC) + rtnl_route_set_protocol (route, value); + else if (prop == NMNL_PROP_TABLE && value != RT_TABLE_UNSPEC) + rtnl_route_set_table (route, value); + else if (prop == NMNL_PROP_SCOPE && value != RT_SCOPE_NOWHERE) + rtnl_route_set_scope (route, value); + else if (prop == NMNL_PROP_PRIO && value > 0) + rtnl_route_set_priority (route, value); + + prop = va_arg (var_args, NmNlProp); + } + va_end (var_args); + + return route; +} + +/** + * nm_netlink_route_add: + * @route: the route to add + * + * Returns: zero if succeeded or the netlink error otherwise. + **/ +int nm_netlink_route_add(struct rtnl_route * route, + int family, + const void * dest, /* in_addr or in6_addr */ + int dest_prefix, + const void * gateway, /* in_addr or in6_addr */ + int flags) +{ + struct nl_sock * sk; + struct nl_addr * dest_addr, * gw_addr; + void * tmp_addr; + int addrlen, err, log; + + if(family == AF_INET) { + addrlen = sizeof(struct in_addr); + log = LOGD_IP4; + } + else if (family == AF_INET6) { + addrlen = sizeof(struct in6_addr); + log = LOGD_IP6; + } else { + g_assert_not_reached (); + } + + + sk = nm_netlink_get_default_handle(); + + /* Build up the destination address */ + if (dest) { + /* Copy to preserve const */ + tmp_addr = g_malloc0(addrlen); + memcpy(tmp_addr, dest, addrlen); + + dest_addr = nl_addr_build (family, tmp_addr, addrlen); + g_free(tmp_addr); + + g_return_val_if_fail (dest_addr != NULL, -NLE_INVAL); + nl_addr_set_prefixlen (dest_addr, dest_prefix); + + rtnl_route_set_dst (route, dest_addr); + nl_addr_put (dest_addr); + } + + /* Build up the gateway address */ + if (gateway) { + tmp_addr = g_malloc0(addrlen); + memcpy(tmp_addr, gateway, addrlen); + + gw_addr = nl_addr_build (family, tmp_addr, addrlen); + g_free(tmp_addr); + + if (gw_addr) { + nl_addr_set_prefixlen (gw_addr, 0); + rtnl_route_set_gateway (route, gw_addr); + rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE); + nl_addr_put(gw_addr); + } else { + nm_log_err (LOGD_DEVICE | log, "Invalid gateway"); + } + } + + err = rtnl_route_add (sk, route, flags); + + /* LIBNL Bug: Aliased ESRCH */ + if (err == -NLE_FAILURE) + err = -NLE_OBJ_NOTFOUND; + + if (err) + nm_log_warn (LOGD_DEVICE | log, + "Failed to add route %s", + nl_geterror(err)); + + return err; +} + +/** + * nm_netlink_route_delete: + * @route: the route to delete + * + * Returns: %TRUE if the request was successful, %FALSE if it failed + **/ +gboolean +nm_netlink_route_delete (struct rtnl_route *route) +{ + struct nl_sock *nlh; + int err = 0; + + g_return_val_if_fail (route != NULL, FALSE); + + nlh = nm_netlink_get_default_handle (); + err = rtnl_route_delete (nlh, route, 0); + + if (err) + nm_log_dbg (LOGD_IP4 | LOGD_IP6, "%s (%d)", nl_geterror(err), err); + + /* Workaround libnl BUG: ESRCH is aliased to generic NLE_FAILURE + * See: http://git.kernel.org/?p=libs/netlink/libnl.git;a=commit;h=7e9d5f */ + if (err == -NLE_FAILURE) + err = -NLE_OBJ_NOTFOUND; + + return (err && (err != -NLE_OBJ_NOTFOUND) && (err != -NLE_RANGE) ) ? FALSE : TRUE; +} + + +static void +dump_route (struct rtnl_route *route) +{ + char buf6[INET6_ADDRSTRLEN]; + char buf4[INET_ADDRSTRLEN]; + struct nl_addr *nl; + struct in6_addr *addr6 = NULL; + struct in_addr *addr4 = NULL; + int prefixlen = 0; + const char *sf = "UNSPEC"; + int family = rtnl_route_get_family (route); + guint32 log_level = LOGD_IP4 | LOGD_IP6; + + memset (buf6, 0, sizeof (buf6)); + memset (buf4, 0, sizeof (buf4)); + nl = rtnl_route_get_dst (route); + if (nl) { + if (nl_addr_get_family (nl) == AF_INET) { + addr4 = nl_addr_get_binary_addr (nl); + if (addr4) + inet_ntop (AF_INET, addr4, &buf4[0], sizeof (buf4)); + } else if (nl_addr_get_family (nl) == AF_INET6) { + addr6 = nl_addr_get_binary_addr (nl); + if (addr6) + inet_ntop (AF_INET6, addr6, &buf6[0], sizeof (buf6)); + } + prefixlen = nl_addr_get_prefixlen (nl); + } + + if (family == AF_INET) { + sf = "INET"; + log_level = LOGD_IP4; + } else if (family == AF_INET6) { + sf = "INET6"; + log_level = LOGD_IP6; + } + + nm_log_dbg (log_level, " route idx %d family %s (%d) addr %s/%d", + rtnl_route_get_oif (route), + sf, family, + strlen (buf4) ? buf4 : (strlen (buf6) ? buf6 : "<unknown>"), + prefixlen); +} + + +typedef struct { + int ifindex; + int family; + int scope; + gboolean ignore_inet6_ll_mc; + const char *iface; + NlRouteForeachFunc callback; + gpointer user_data; + struct rtnl_route *out_route; +} ForeachRouteInfo; + +static void +foreach_route_cb (struct nl_object *object, void *user_data) +{ + ForeachRouteInfo *info = user_data; + struct rtnl_route *route = (struct rtnl_route *) object; + struct nl_addr *dst; + + if (info->out_route) + return; + + if (nm_logging_level_enabled (LOGL_DEBUG)) + dump_route (route); + + if ( info->ifindex >= 0 + && rtnl_route_get_oif (route) != info->ifindex) + return; + + if ( info->scope != RT_SCOPE_UNIVERSE + && rtnl_route_get_scope (route) != info->scope) + return; + + if ( info->family != AF_UNSPEC + && rtnl_route_get_family (route) != info->family) + return; + + dst = rtnl_route_get_dst (route); + + /* Check for IPv6 LL and MC routes that might need to be ignored */ + if ( (info->family == AF_INET6 || info->family == AF_UNSPEC) + && (rtnl_route_get_family (route) == AF_INET6)) { + struct in6_addr *addr = NULL; + + if (dst) + addr = nl_addr_get_binary_addr (dst); + if (addr) { + if ( IN6_IS_ADDR_LINKLOCAL (addr) + || IN6_IS_ADDR_MC_LINKLOCAL (addr) + || (IN6_IS_ADDR_MULTICAST (addr) && (nl_addr_get_prefixlen (dst) == 8))) + return; + } + } + + info->out_route = info->callback (route, dst, info->iface, info->user_data); + if (info->out_route) { + /* Ref the route so it sticks around after the cache is cleared */ + rtnl_route_get (info->out_route); + } +} + +/** + * nm_netlink_foreach_route: + * @ifindex: the interface index to filter routes for + * @family: the address family to filter routes for + * @scope: route scope, eg RT_SCOPE_LINK + * @ignore_inet6_ll_mc: if %TRUE ignore IPv6 link-local and multi-cast routes + * @callback: function called when a route matches the filter + * @user_data: data passed to @callback + * + * Filters each route in the routing table against the given @ifindex and + * @family (if given) and calls @callback for each matching route. + * + * Returns: a route if @callback returned one; the caller must dispose of the + * route using rtnl_route_put() when it is no longer required. + **/ +struct rtnl_route * +nm_netlink_foreach_route (int ifindex, + int family, + int scope, + gboolean ignore_inet6_ll_mc, + NlRouteForeachFunc callback, + gpointer user_data) +{ + struct nl_cache *cache; + ForeachRouteInfo info; + + memset (&info, 0, sizeof (info)); + info.ifindex = ifindex; + info.family = family; + info.scope = scope; + info.ignore_inet6_ll_mc = ignore_inet6_ll_mc; + info.callback = callback; + info.user_data = user_data; + info.iface = nm_netlink_index_to_iface (ifindex); + + rtnl_route_alloc_cache (nm_netlink_get_default_handle (), family, NL_AUTO_PROVIDE, &cache); + g_return_val_if_fail (cache != NULL, NULL); + nl_cache_foreach (cache, foreach_route_cb, &info); + nl_cache_free (cache); + return info.out_route; +} + + diff --git a/src/nm-netlink-utils.h b/src/nm-netlink-utils.h new file mode 100644 index 00000000..c6c452a0 --- /dev/null +++ b/src/nm-netlink-utils.h @@ -0,0 +1,80 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + */ + +#ifndef NM_NETLINK_UTILS_H +#define NM_NETLINK_UTILS_H + +#include <glib.h> +#include <netlink/route/rtnl.h> +#include <netlink/route/route.h> + +gboolean nm_netlink_find_address (int ifindex, + int family, + void *addr, /* struct in_addr or struct in6_addr */ + int prefix_); + +typedef enum { + NMNL_PROP_INVALID = 0, + NMNL_PROP_PROT, + NMNL_PROP_SCOPE, + NMNL_PROP_TABLE, + NMNL_PROP_PRIO, +} NmNlProp; + +struct rtnl_route * nm_netlink_route_new (int ifindex, + int family, + int mss, + ...) __attribute__((__sentinel__)); + +int nm_netlink_route_add (struct rtnl_route *route, + int family, + const void * dst, /* struct in_addr or struct in6_addr */ + int prefix, + const void * gw, /* struct in_addr or struct in6_addr */ + int flags); + +gboolean nm_netlink_route_delete (struct rtnl_route *route); + +/** + * NlRouteForeachFunc: + * @route: the route being processed + * @dst: the route's destination address + * @iface: the interface name of the index passed to nm_netlink_foreach_route() + * @in_family: the address family passed to nm_netlink_foreach_route() + * @user_data: the user data pointer passed to nm_netlink_foreach_route() + * + * Returns: a route to return to the caller of nm_netlink_foreach_route() which + * terminates routing table iteration, or NULL to continue iterating the + * routing table. + **/ +typedef struct rtnl_route * (*NlRouteForeachFunc) (struct rtnl_route *route, + struct nl_addr *dst, + const char *iface, + gpointer user_data); + +struct rtnl_route * nm_netlink_foreach_route (int ifindex, + int family, + int scope, + gboolean ignore_inet6_ll_mc, + NlRouteForeachFunc callback, + gpointer user_data); + +#endif /* NM_NETLINK_MONITOR_H */ + diff --git a/src/nm-policy.c b/src/nm-policy.c index a42a0fa9..02292f7a 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -425,6 +425,7 @@ update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update) NMConnection *connection = NULL; NMSettingConnection *s_con = NULL; const char *connection_id; + int ip_ifindex = 0; best = get_best_ip4_device (policy->manager, &best_req); if (!best) @@ -461,17 +462,18 @@ update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update) NMDevice *parent; ip_iface = nm_vpn_connection_get_ip_iface (candidate); + ip_ifindex = nm_vpn_connection_get_ip_ifindex (candidate); connection = nm_vpn_connection_get_connection (candidate); addr = nm_ip4_config_get_address (ip4_config, 0); parent = nm_vpn_connection_get_parent_device (candidate); parent_ip4 = nm_device_get_ip4_config (parent); - nm_system_replace_default_ip4_route_vpn (ip_iface, + nm_system_replace_default_ip4_route_vpn (ip_ifindex, nm_ip4_address_get_gateway (addr), nm_vpn_connection_get_ip4_internal_gateway (candidate), nm_ip4_config_get_mss (ip4_config), - nm_device_get_ip_iface (parent), + nm_device_get_ip_ifindex (parent), nm_ip4_config_get_mss (parent_ip4)); dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -483,12 +485,14 @@ update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update) if (!ip_iface || !ip4_config) { connection = nm_act_request_get_connection (best_req); ip_iface = nm_device_get_ip_iface (best); + ip_ifindex = nm_device_get_ip_ifindex (best); ip4_config = nm_device_get_ip4_config (best); g_assert (ip4_config); addr = nm_ip4_config_get_address (ip4_config, 0); - nm_system_replace_default_ip4_route (ip_iface, nm_ip4_address_get_gateway (addr), nm_ip4_config_get_mss (ip4_config)); - + nm_system_replace_default_ip4_route (ip_ifindex, + nm_ip4_address_get_gateway (addr), + nm_ip4_config_get_mss (ip4_config)); dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; } @@ -551,6 +555,7 @@ update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update) NMIP6Config *ip6_config = NULL; NMIP6Address *addr; const char *ip_iface = NULL; + int ip_ifindex = -1; NMConnection *connection = NULL; NMSettingConnection *s_con = NULL; const char *connection_id; @@ -608,11 +613,12 @@ update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update) if (!ip_iface || !ip6_config) { connection = nm_act_request_get_connection (best_req); ip_iface = nm_device_get_ip_iface (best); + ip_ifindex = nm_device_get_ip_ifindex (best); ip6_config = nm_device_get_ip6_config (best); g_assert (ip6_config); addr = nm_ip6_config_get_address (ip6_config, 0); - nm_system_replace_default_ip6_route (ip_iface, nm_ip6_address_get_gateway (addr)); + nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_address_get_gateway (addr)); dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; } diff --git a/src/nm-system.c b/src/nm-system.c index 88db6596..0b294684 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -48,9 +48,8 @@ #include "nm-utils.h" #include "nm-logging.h" #include "nm-netlink-monitor.h" - -/* Because of a bug in libnl, rtnl.h should be included before route.h */ -#include <netlink/route/rtnl.h> +#include "nm-netlink-utils.h" +#include "nm-netlink-compat.h" #include <netlink/route/addr.h> #include <netlink/route/route.h> @@ -58,9 +57,9 @@ #include <netlink/utils.h> #include <netlink/route/link.h> -static void nm_system_device_set_priority (const char *iface, - NMIP4Config *config, - int priority); +static void nm_system_device_set_priority (int ifindex, + NMIP4Config *config, + int priority); static gboolean ip4_dest_in_same_subnet (NMIP4Config *config, guint32 dest, guint32 dest_prefix) @@ -87,99 +86,54 @@ ip4_dest_in_same_subnet (NMIP4Config *config, guint32 dest, guint32 dest_prefix) } static struct rtnl_route * -create_route (int iface_idx, int mss) -{ - struct rtnl_route *route; - - route = rtnl_route_alloc (); - if (route) { - rtnl_route_set_oif (route, iface_idx); - - if (mss && rtnl_route_set_metric (route, RTAX_ADVMSS, mss) < 0) { - nm_log_warn (LOGD_DEVICE, "could not set mss"); - } - } else - nm_log_err (LOGD_DEVICE, "could not allocate route"); - - return route; -} - -static struct rtnl_route * -nm_system_device_set_ip4_route (const char *iface, +nm_system_device_set_ip4_route (int ifindex, guint32 ip4_dest, guint32 ip4_prefix, guint32 ip4_gateway, guint32 metric, int mss) { - struct nl_handle *nlh; + struct nl_sock *nlh; struct rtnl_route *route; - struct nl_addr *dest_addr; - struct nl_addr *gw_addr = NULL; - int err, iface_idx; + int err; + const char *iface; + + g_return_val_if_fail (ifindex > 0, NULL); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, NULL); - iface_idx = nm_netlink_iface_to_index (iface); - g_return_val_if_fail (iface_idx >= 0, NULL); + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, NULL); - route = create_route (iface_idx, mss); + route = nm_netlink_route_new (ifindex, AF_INET, mss, + NMNL_PROP_PRIO, metric, + NULL); g_return_val_if_fail (route != NULL, NULL); - /* Destination */ - dest_addr = nl_addr_build (AF_INET, &ip4_dest, sizeof (ip4_dest)); - g_return_val_if_fail (dest_addr != NULL, NULL); - nl_addr_set_prefixlen (dest_addr, (int) ip4_prefix); - - rtnl_route_set_dst (route, dest_addr); - nl_addr_put (dest_addr); - - /* Gateway */ - if (ip4_gateway) { - gw_addr = nl_addr_build (AF_INET, &ip4_gateway, sizeof (ip4_gateway)); - if (gw_addr) { - rtnl_route_set_gateway (route, gw_addr); - rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE); - } else { - nm_log_err (LOGD_DEVICE | LOGD_IP4, "Invalid gateway 0x%X", ip4_gateway); - rtnl_route_put (route); - return NULL; - } - } - - /* Metric */ - if (metric) - rtnl_route_set_prio (route, metric); - /* Add the route */ - err = rtnl_route_add (nlh, route, 0); - if (err == -ESRCH && ip4_gateway) { + err = nm_netlink_route_add(route, AF_INET, &ip4_dest, ip4_prefix, &ip4_gateway, 0); + if (err == -NLE_OBJ_NOTFOUND && ip4_gateway) { /* Gateway might be over a bridge; try adding a route to gateway first */ struct rtnl_route *route2; - route2 = create_route (iface_idx, mss); + route2 = nm_netlink_route_new (ifindex, AF_INET, mss, NULL); if (route2) { /* Add route to gateway over bridge */ - rtnl_route_set_dst (route2, gw_addr); - err = rtnl_route_add (nlh, route2, 0); + err = nm_netlink_route_add(route2, AF_INET, &ip4_gateway, 32, NULL, 0); if (!err) { - /* Try adding the route again */ - err = rtnl_route_add (nlh, route, 0); + err = nm_netlink_route_add(route, AF_INET, &ip4_dest, ip4_prefix, &ip4_gateway, 0); if (err) - rtnl_route_del (nlh, route2, 0); + nm_netlink_route_delete (route2); } rtnl_route_put (route2); } } - if (gw_addr) - nl_addr_put (gw_addr); - if (err) { nm_log_err (LOGD_DEVICE | LOGD_IP4, "(%s): failed to set IPv4 route: %s", - iface, nl_geterror ()); + iface, nl_geterror (err)); rtnl_route_put (route); route = NULL; } @@ -188,10 +142,12 @@ nm_system_device_set_ip4_route (const char *iface, } static gboolean -sync_addresses (const char *iface, int ifindex, int family, - struct rtnl_addr **addrs, int num_addrs) +sync_addresses (int ifindex, + int family, + struct rtnl_addr **addrs, + int num_addrs) { - struct nl_handle *nlh; + struct nl_sock *nlh; struct nl_cache *addr_cache; struct rtnl_addr *filter_addr, *match_addr; struct nl_object *match; @@ -199,6 +155,10 @@ sync_addresses (const char *iface, int ifindex, int family, int i, err; guint32 log_domain = (family == AF_INET) ? LOGD_IP4 : LOGD_IP6; char buf[INET6_ADDRSTRLEN + 1]; + const char *iface; + + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); log_domain |= LOGD_DEVICE; @@ -206,8 +166,8 @@ sync_addresses (const char *iface, int ifindex, int family, if (!nlh) return FALSE; - addr_cache = rtnl_addr_alloc_cache (nlh); - if (!addr_cache) + err = rtnl_addr_alloc_cache (nlh, &addr_cache); + if (err < 0) return FALSE; filter_addr = rtnl_addr_alloc (); @@ -279,7 +239,7 @@ sync_addresses (const char *iface, int ifindex, int family, err = rtnl_addr_delete (nlh, match_addr, 0); if (err < 0) { nm_log_err (log_domain, "(%s): error %d returned from rtnl_addr_delete(): %s", - iface, err, nl_geterror ()); + iface, err, nl_geterror (err)); } } @@ -312,10 +272,10 @@ sync_addresses (const char *iface, int ifindex, int family, } err = rtnl_addr_add (nlh, addrs[i], 0); - if (err < 0 && (nl_get_errno () != EEXIST)) { + if (err < 0 && (err != -NLE_EXIST)) { nm_log_err (log_domain, "(%s): error %d returned from rtnl_addr_add():\n%s", - iface, err, nl_geterror ()); + iface, err, nl_geterror (err)); } rtnl_addr_put (addrs[i]); @@ -361,7 +321,7 @@ add_ip4_addresses (NMIP4Config *config, const char *iface) rtnl_addr_set_ifindex (addrs[i], iface_idx); } - return sync_addresses (iface, iface_idx, AF_INET, addrs, num_addrs); + return sync_addresses (iface_idx, AF_INET, addrs, num_addrs); } struct rtnl_route * @@ -406,10 +366,10 @@ nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_c * parent device. */ if (ip4_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix)) { - route = nm_system_device_set_ip4_route (nm_device_get_ip_iface (parent_device), + route = nm_system_device_set_ip4_route (nm_device_get_ip_ifindex (parent_device), vpn_gw, 32, 0, 0, nm_ip4_config_get_mss (parent_config)); } else { - route = nm_system_device_set_ip4_route (nm_device_get_ip_iface (parent_device), + route = nm_system_device_set_ip4_route (nm_device_get_ip_ifindex (parent_device), vpn_gw, 32, parent_gw, 0, nm_ip4_config_get_mss (parent_config)); } @@ -423,16 +383,20 @@ nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_c * */ gboolean -nm_system_apply_ip4_config (const char *iface, +nm_system_apply_ip4_config (int ifindex, NMIP4Config *config, int priority, NMIP4ConfigCompareFlags flags) { + const char *iface; int i; - g_return_val_if_fail (iface != NULL, FALSE); + g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (config != NULL, FALSE); + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); + if (flags & NM_IP4_COMPARE_FLAG_ADDRESSES) { if (!add_ip4_addresses (config, iface)) return FALSE; @@ -459,7 +423,7 @@ nm_system_apply_ip4_config (const char *iface, && nm_ip4_route_get_dest (route) == 0) continue; - tmp = nm_system_device_set_ip4_route (iface, + tmp = nm_system_device_set_ip4_route (ifindex, nm_ip4_route_get_dest (route), nm_ip4_route_get_prefix (route), nm_ip4_route_get_next_hop (route), @@ -471,11 +435,11 @@ nm_system_apply_ip4_config (const char *iface, if (flags & NM_IP4_COMPARE_FLAG_MTU) { if (nm_ip4_config_get_mtu (config)) - nm_system_device_set_mtu (iface, nm_ip4_config_get_mtu (config)); + nm_system_iface_set_mtu (ifindex, nm_ip4_config_get_mtu (config)); } if (priority > 0) - nm_system_device_set_priority (iface, config, priority); + nm_system_device_set_priority (ifindex, config, priority); return TRUE; } @@ -491,10 +455,8 @@ nm_system_set_ip6_route (int ifindex, int table, struct rtnl_route **out_route) { - struct nl_handle *nlh; + struct nl_sock *nlh; struct rtnl_route *route; - struct nl_addr *dest_addr; - struct nl_addr *gw_addr = NULL; int err = 0; g_return_val_if_fail (ifindex >= 0, -1); @@ -502,64 +464,33 @@ nm_system_set_ip6_route (int ifindex, nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, -1); - route = create_route (ifindex, mss); + route = nm_netlink_route_new (ifindex, AF_INET6, mss, + NMNL_PROP_PROT, protocol, + NMNL_PROP_PRIO, metric, + NMNL_PROP_TABLE, table, + NULL); g_return_val_if_fail (route != NULL, -1); - /* Destination */ - dest_addr = nl_addr_build (AF_INET6, (struct in6_addr *) ip6_dest, sizeof (*ip6_dest)); - g_return_val_if_fail (dest_addr != NULL, -1); - nl_addr_set_prefixlen (dest_addr, (int) ip6_prefix); - - rtnl_route_set_dst (route, dest_addr); - nl_addr_put (dest_addr); - - /* Gateway */ - if (ip6_gateway && !IN6_IS_ADDR_UNSPECIFIED (ip6_gateway)) { - gw_addr = nl_addr_build (AF_INET6, (struct in6_addr *) ip6_gateway, sizeof (*ip6_gateway)); - if (gw_addr) { - rtnl_route_set_gateway (route, gw_addr); - rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE); - } else { - nm_log_warn (LOGD_DEVICE | LOGD_IP6, "Invalid gateway"); - rtnl_route_put (route); - return -1; - } - } - - /* Metric */ - if (metric) - rtnl_route_set_prio (route, metric); - - if (protocol) - rtnl_route_set_protocol (route, protocol); - - if (table) - rtnl_route_set_table (route, table); - /* Add the route */ - err = rtnl_route_add (nlh, route, 0); - if (err == -ESRCH && ip6_gateway) { + err = nm_netlink_route_add(route, AF_INET6, &ip6_dest, ip6_prefix, &ip6_gateway, 0); + if (err == -NLE_OBJ_NOTFOUND && ip6_gateway) { /* Gateway might be over a bridge; try adding a route to gateway first */ struct rtnl_route *route2; - route2 = create_route (ifindex, mss); + route2 = nm_netlink_route_new (ifindex, AF_INET6, mss, NULL); if (route2) { + err = nm_netlink_route_add(route, AF_INET6, &ip6_gateway, 128, NULL, 0); /* Add route to gateway over bridge */ - rtnl_route_set_dst (route2, gw_addr); - err = rtnl_route_add (nlh, route2, 0); if (!err) { /* Try adding the route again */ - err = rtnl_route_add (nlh, route, 0); + err = nm_netlink_route_add(route, AF_INET6, &ip6_dest, ip6_prefix, &ip6_gateway, 0); if (err) - rtnl_route_del (nlh, route2, 0); + nm_netlink_route_delete (route2); } rtnl_route_put (route2); } } - if (gw_addr) - nl_addr_put (gw_addr); - if (out_route) *out_route = route; else @@ -595,7 +526,7 @@ add_ip6_addresses (NMIP6Config *config, const char *iface) rtnl_addr_set_ifindex (addrs[i], iface_idx); } - return sync_addresses (iface, iface_idx, AF_INET6, addrs, num_addrs); + return sync_addresses (iface_idx, AF_INET6, addrs, num_addrs); } /* @@ -605,16 +536,20 @@ add_ip6_addresses (NMIP6Config *config, const char *iface) * */ gboolean -nm_system_apply_ip6_config (const char *iface, +nm_system_apply_ip6_config (int ifindex, NMIP6Config *config, int priority, NMIP6ConfigCompareFlags flags) { + const char *iface; int i; - g_return_val_if_fail (iface != NULL, FALSE); + g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (config != NULL, FALSE); + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); + if (flags & NM_IP6_COMPARE_FLAG_ADDRESSES) { if (!add_ip6_addresses (config, iface)) return FALSE; @@ -622,8 +557,6 @@ nm_system_apply_ip6_config (const char *iface, } if (flags & NM_IP6_COMPARE_FLAG_ROUTES) { - int ifindex = nm_netlink_iface_to_index (iface); - for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) { NMIP6Route *route = nm_ip6_config_get_route (config, i); int err; @@ -647,7 +580,7 @@ nm_system_apply_ip6_config (const char *iface, if (err) { nm_log_err (LOGD_DEVICE | LOGD_IP6, "(%s): failed to set IPv6 route: %s", - iface, nl_geterror ()); + iface, nl_geterror (err)); } } } @@ -659,166 +592,182 @@ nm_system_apply_ip6_config (const char *iface, return TRUE; } -/* - * nm_system_device_set_up_down +/** + * nm_system_iface_set_up: + * @ifindex: interface index + * @up: %TRUE to bring interface up, or %FALSE to take it down + * @no_firmware: on return, %TRUE if the operation may have failed due to + * missing firmware * - * Mark the device as up or down. + * Bring the interface up or take it down. * - */ + * Returns: %TRUE on success, %FALSE on failure + **/ gboolean -nm_system_device_set_up_down (NMDevice *dev, - gboolean up, - gboolean *no_firmware) -{ - g_return_val_if_fail (dev != NULL, FALSE); - - return nm_system_device_set_up_down_with_iface (nm_device_get_ip_iface (dev), up, no_firmware); -} - -gboolean -nm_system_device_set_up_down_with_iface (const char *iface, - gboolean up, - gboolean *no_firmware) +nm_system_iface_set_up (int ifindex, + gboolean up, + gboolean *no_firmware) { struct rtnl_link *request = NULL, *old = NULL; - struct nl_handle *nlh; + struct nl_sock *nlh; gboolean success = FALSE; - guint32 idx; + int err; - g_return_val_if_fail (iface != NULL, FALSE); + g_return_val_if_fail (ifindex > 0, FALSE); if (no_firmware) g_return_val_if_fail (*no_firmware == FALSE, FALSE); if (!(request = rtnl_link_alloc ())) - goto out; + return FALSE; if (up) rtnl_link_set_flags (request, IFF_UP); else rtnl_link_unset_flags (request, IFF_UP); - idx = nm_netlink_iface_to_index (iface); - old = nm_netlink_index_to_rtnl_link (idx); + old = nm_netlink_index_to_rtnl_link (ifindex); if (old) { nlh = nm_netlink_get_default_handle (); if (nlh) { - if (rtnl_link_change (nlh, old, request, 0) == 0) + err = rtnl_link_change (nlh, old, request, 0); + if (err == 0) { success = TRUE; - else if ((nl_get_errno () == ENOENT) && no_firmware && up) - *no_firmware = TRUE; + } else { + if ((err == -NLE_OBJ_NOTFOUND) && no_firmware && up) + *no_firmware = TRUE; + } } } rtnl_link_put (old); rtnl_link_put (request); - -out: return success; } +/** + * nm_system_iface_is_up: + * @ifindex: interface index + * + * Returns: %TRUE if the interface is up, %FALSE if it was down or the check + * failed. + **/ gboolean -nm_system_device_is_up (NMDevice *device) +nm_system_iface_is_up (int ifindex) { - g_return_val_if_fail (device != NULL, FALSE); + const char *iface; + struct rtnl_link *l; + guint32 flags; - return nm_system_device_is_up_with_iface (nm_device_get_ip_iface (device)); -} + g_return_val_if_fail (ifindex > 0, FALSE); -gboolean -nm_system_device_is_up_with_iface (const char *iface) -{ - struct ifreq ifr; - int fd; - gboolean up = FALSE; + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - nm_log_err (LOGD_HW, "couldn't open control socket."); + l = nm_netlink_index_to_rtnl_link (ifindex); + if (l == NULL) { + nm_log_err (LOGD_HW, "(%s): failed to get interface link object", iface); return FALSE; } - /* Get device's flags */ - memset (&ifr, 0, sizeof (ifr)); - strncpy (ifr.ifr_name, iface, IFNAMSIZ); - if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0) { - if (errno != ENODEV) { - nm_log_err (LOGD_HW, "(%s): could not get flags: errno %d", - iface, errno); - } - } else { - up = !!(ifr.ifr_flags & IFF_UP); - } - close (fd); + flags = rtnl_link_get_flags (l); + rtnl_link_put (l); - return up; + return flags & IFF_UP; } +/** + * nm_system_iface_set_mtu: + * @ifindex: interface index + * @mtu: the new MTU + * + * Returns: %TRUE if the request was successful, %FALSE if it failed + **/ gboolean -nm_system_device_set_mtu (const char *iface, guint32 mtu) +nm_system_iface_set_mtu (int ifindex, guint32 mtu) { struct rtnl_link *old; struct rtnl_link *new; gboolean success = FALSE; - struct nl_handle *nlh; - int iface_idx; + struct nl_sock *nlh; + const char *iface; + int err; - g_return_val_if_fail (iface != NULL, FALSE); + g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (mtu > 0, FALSE); + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); + new = rtnl_link_alloc (); if (!new) return FALSE; - iface_idx = nm_netlink_iface_to_index (iface); - old = nm_netlink_index_to_rtnl_link (iface_idx); + old = nm_netlink_index_to_rtnl_link (ifindex); if (old) { rtnl_link_set_mtu (new, mtu); nlh = nm_netlink_get_default_handle (); if (nlh) { - rtnl_link_change (nlh, old, new, 0); - success = TRUE; + err = rtnl_link_change (nlh, old, new, 0); + if (err == 0) + success = TRUE; + else + nm_log_warn (LOGD_HW, "(%s): failed to change interface MTU", iface); } rtnl_link_put (old); } - rtnl_link_put (new); + return success; } +/** + * nm_system_iface_set_mac: + * @ifindex: interface index + * @mac: new MAC address + * + * Attempts to change the interface's MAC address to the requested value, + * ie MAC spoofing or cloning. + * + * Returns: %TRUE if the request succeeded, %FALSE if it failed. + **/ gboolean -nm_system_device_set_mac (const char *iface, const struct ether_addr *mac) +nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac) { - struct rtnl_link *old; - struct rtnl_link *new; + struct rtnl_link *old, *new; gboolean success = FALSE; - struct nl_handle *nlh; - int iface_idx; + struct nl_sock *nlh; + const char *iface; struct nl_addr *addr = NULL; + int err; - g_return_val_if_fail (iface != NULL, FALSE); + g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (mac != NULL, FALSE); + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); + new = rtnl_link_alloc (); if (!new) return FALSE; - iface_idx = nm_netlink_iface_to_index (iface); - old = nm_netlink_index_to_rtnl_link (iface_idx); + old = nm_netlink_index_to_rtnl_link (ifindex); if (old) { addr = nl_addr_build (AF_LLC, (void *) mac, ETH_ALEN); if (!addr) { - char *mac_str; - mac_str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", mac->ether_addr_octet[0], mac->ether_addr_octet[1], mac->ether_addr_octet[2], - mac->ether_addr_octet[3], mac->ether_addr_octet[4], mac->ether_addr_octet[5]); - nm_log_err (LOGD_DEVICE, "(%s): could not allocate memory for MAC address (%s)", iface, mac_str); - g_free (mac_str); + nm_log_err (LOGD_HW, "(%s): failed to allocate memory for MAC address change", iface); + rtnl_link_put (old); + rtnl_link_put (new); return FALSE; } rtnl_link_set_addr (new, addr); + nl_addr_put (addr); nlh = nm_netlink_get_default_handle (); if (nlh) { - rtnl_link_change (nlh, old, new, 0); - success = TRUE; + err = rtnl_link_change (nlh, old, new, 0); + if (err == 0) + success = TRUE; + else + nm_log_warn (LOGD_HW, "(%s): failed to change interface MAC address", iface); } rtnl_link_put (old); } @@ -828,44 +777,28 @@ nm_system_device_set_mac (const char *iface, const struct ether_addr *mac) } static struct rtnl_route * -add_ip4_route_to_gateway (const char *iface, guint32 gw, guint32 mss) +add_ip4_route_to_gateway (int ifindex, guint32 gw, guint32 mss) { - struct nl_handle *nlh; + struct nl_sock *nlh; struct rtnl_route *route = NULL; - struct nl_addr *gw_addr = NULL; - int iface_idx, err; + const char *iface; + int err; + + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, NULL); - iface_idx = nm_netlink_iface_to_index (iface); - if (iface_idx < 0) - return NULL; - /* Gateway might be over a bridge; try adding a route to gateway first */ - route = rtnl_route_alloc (); - if (route == NULL) - return NULL; - - rtnl_route_set_family (route, AF_INET); - rtnl_route_set_table (route, RT_TABLE_MAIN); - rtnl_route_set_oif (route, iface_idx); - rtnl_route_set_scope (route, RT_SCOPE_LINK); - - gw_addr = nl_addr_build (AF_INET, &gw, sizeof (gw)); - if (!gw_addr) - goto error; - nl_addr_set_prefixlen (gw_addr, 32); - rtnl_route_set_dst (route, gw_addr); - nl_addr_put (gw_addr); - - if (mss) { - if (rtnl_route_set_metric (route, RTAX_ADVMSS, mss) < 0) - goto error; - } + route = nm_netlink_route_new (ifindex, AF_INET, mss, + NMNL_PROP_SCOPE, RT_SCOPE_LINK, + NMNL_PROP_TABLE, RT_TABLE_MAIN, + NULL); + g_return_val_if_fail (route != NULL, NULL); /* Add direct route to the gateway */ - err = rtnl_route_add (nlh, route, 0); + err = nm_netlink_route_add(route, AF_INET, &gw, 32, NULL, 0); if (err) { nm_log_err (LOGD_DEVICE | LOGD_IP4, "(%s): failed to add IPv4 route to gateway (%d)", @@ -881,64 +814,27 @@ error: } static int -replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss) +replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) { struct rtnl_route *route = NULL; - struct nl_handle *nlh; - struct nl_addr *dst_addr = NULL; - guint32 dst = 0; - struct nl_addr *gw_addr = NULL; - int iface_idx, err = -1; + struct nl_sock *nlh; + int err = -1; + int dst=0; - g_return_val_if_fail (iface != NULL, -ENODEV); + g_return_val_if_fail (ifindex > 0, -ENODEV); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, -ENOMEM); - iface_idx = nm_netlink_iface_to_index (iface); - if (iface_idx < 0) - return -ENODEV; - - route = rtnl_route_alloc(); + route = nm_netlink_route_new (ifindex, AF_INET, mss, + NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE, + NMNL_PROP_TABLE, RT_TABLE_MAIN, + NULL); g_return_val_if_fail (route != NULL, -ENOMEM); - rtnl_route_set_family (route, AF_INET); - rtnl_route_set_table (route, RT_TABLE_MAIN); - rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE); - rtnl_route_set_oif (route, iface_idx); - - /* Build up the destination address */ - dst_addr = nl_addr_build (AF_INET, &dst, sizeof (dst)); - if (!dst_addr) { - err = -ENOMEM; - goto out; - } - nl_addr_set_prefixlen (dst_addr, 0); - rtnl_route_set_dst (route, dst_addr); - - /* Build up the gateway address */ - gw_addr = nl_addr_build (AF_INET, &gw, sizeof (gw)); - if (!gw_addr) { - err = -ENOMEM; - goto out; - } - nl_addr_set_prefixlen (gw_addr, 0); - rtnl_route_set_gateway (route, gw_addr); - - if (mss > 0) { - err = rtnl_route_set_metric (route, RTAX_ADVMSS, mss); - if (err < 0) - goto out; - } - /* Add the new default route */ - err = rtnl_route_add (nlh, route, NLM_F_REPLACE); + err = nm_netlink_route_add (route, AF_INET, &dst, 0, &gw, NLM_F_REPLACE); -out: - if (dst_addr) - nl_addr_put (dst_addr); - if (gw_addr) - nl_addr_put (gw_addr); rtnl_route_put (route); return err; } @@ -950,25 +846,29 @@ out: * */ gboolean -nm_system_replace_default_ip4_route_vpn (const char *iface, +nm_system_replace_default_ip4_route_vpn (int ifindex, guint32 ext_gw, guint32 int_gw, guint32 mss, - const char *parent_iface, + int parent_ifindex, guint32 parent_mss) { struct rtnl_route *gw_route = NULL; - struct nl_handle *nlh; + struct nl_sock *nlh; gboolean success = FALSE; int err; + const char *iface; + + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, FALSE); - err = replace_default_ip4_route (iface, int_gw, mss); + err = replace_default_ip4_route (ifindex, int_gw, mss); if (err == 0) { return TRUE; - } else if (err != -ESRCH) { + } else if ((err != -NLE_OBJ_NOTFOUND) && (err != -NLE_FAILURE)) { nm_log_err (LOGD_DEVICE | LOGD_IP4, "(%s): failed to set IPv4 default route: %d", iface, err); @@ -976,14 +876,14 @@ nm_system_replace_default_ip4_route_vpn (const char *iface, } /* Try adding a direct route to the gateway first */ - gw_route = add_ip4_route_to_gateway (parent_iface, ext_gw, parent_mss); + gw_route = add_ip4_route_to_gateway (parent_ifindex, ext_gw, parent_mss); if (!gw_route) return FALSE; /* Try adding the original route again */ - err = replace_default_ip4_route (iface, int_gw, mss); + err = replace_default_ip4_route (ifindex, int_gw, mss); if (err != 0) { - rtnl_route_del (nlh, gw_route, 0); + nm_netlink_route_delete (gw_route); nm_log_err (LOGD_DEVICE | LOGD_IP4, "(%s): failed to set IPv4 default route (pass #2): %d", iface, err); @@ -1001,20 +901,20 @@ nm_system_replace_default_ip4_route_vpn (const char *iface, * */ gboolean -nm_system_replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss) +nm_system_replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss) { struct rtnl_route *gw_route = NULL; - struct nl_handle *nlh; gboolean success = FALSE; + const char *iface; int err; - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); - err = replace_default_ip4_route (iface, gw, mss); + err = replace_default_ip4_route (ifindex, gw, mss); if (err == 0) { return TRUE; - } else if (err != -ESRCH) { + } else if (err != -NLE_OBJ_NOTFOUND) { nm_log_err (LOGD_DEVICE | LOGD_IP4, "(%s): failed to set IPv4 default route: %d", iface, err); @@ -1022,14 +922,14 @@ nm_system_replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss) } /* Try adding a direct route to the gateway first */ - gw_route = add_ip4_route_to_gateway (iface, gw, mss); + gw_route = add_ip4_route_to_gateway (ifindex, gw, mss); if (!gw_route) return FALSE; /* Try adding the original route again */ - err = replace_default_ip4_route (iface, gw, mss); + err = replace_default_ip4_route (ifindex, gw, mss); if (err != 0) { - rtnl_route_del (nlh, gw_route, 0); + nm_netlink_route_delete (gw_route); nm_log_err (LOGD_DEVICE | LOGD_IP4, "(%s): failed to set IPv4 default route (pass #2): %d", iface, err); @@ -1041,39 +941,28 @@ nm_system_replace_default_ip4_route (const char *iface, guint32 gw, guint32 mss) } static struct rtnl_route * -add_ip6_route_to_gateway (const char *iface, const struct in6_addr *gw) +add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw) { - struct nl_handle *nlh; + struct nl_sock *nlh; struct rtnl_route *route = NULL; - struct nl_addr *gw_addr = NULL; - int iface_idx, err; + const char *iface; + int err; + + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, NULL); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, NULL); - iface_idx = nm_netlink_iface_to_index (iface); - if (iface_idx < 0) - return NULL; - /* Gateway might be over a bridge; try adding a route to gateway first */ - route = rtnl_route_alloc (); - if (route == NULL) - return NULL; - - rtnl_route_set_family (route, AF_INET6); - rtnl_route_set_table (route, RT_TABLE_MAIN); - rtnl_route_set_oif (route, iface_idx); - rtnl_route_set_scope (route, RT_SCOPE_LINK); - - gw_addr = nl_addr_build (AF_INET, (void *) gw, sizeof (*gw)); - if (!gw_addr) - goto error; - nl_addr_set_prefixlen (gw_addr, 128); - rtnl_route_set_dst (route, gw_addr); - nl_addr_put (gw_addr); + route = nm_netlink_route_new (ifindex, AF_INET6, 0, + NMNL_PROP_SCOPE, RT_SCOPE_LINK, + NMNL_PROP_TABLE, RT_TABLE_MAIN, + NULL); + g_return_val_if_fail (route != NULL, NULL); /* Add direct route to the gateway */ - err = rtnl_route_add (nlh, route, 0); + err = nm_netlink_route_add(route, AF_INET, gw, 128, NULL, 0); if (err) { nm_log_err (LOGD_DEVICE | LOGD_IP6, "(%s): failed to add IPv4 route to gateway (%d)", @@ -1089,44 +978,30 @@ error: } static int -replace_default_ip6_route (const char *iface, const struct in6_addr *gw) +replace_default_ip6_route (int ifindex, const struct in6_addr *gw) { struct rtnl_route *route = NULL; - struct nl_handle *nlh; - struct nl_addr *gw_addr = NULL; - int iface_idx, err = -1; + struct nl_sock *nlh; + const char *iface; + int err = -1; - g_return_val_if_fail (iface != NULL, -ENODEV); + g_return_val_if_fail (ifindex > 0, FALSE); + + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, -ENOMEM); - iface_idx = nm_netlink_iface_to_index (iface); - if (iface_idx < 0) - return -ENODEV; - - route = rtnl_route_alloc(); + route = nm_netlink_route_new (ifindex, AF_INET6, 0, + NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE, + NMNL_PROP_TABLE, RT_TABLE_MAIN, + NULL); g_return_val_if_fail (route != NULL, -ENOMEM); - rtnl_route_set_family (route, AF_INET6); - rtnl_route_set_table (route, RT_TABLE_MAIN); - rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE); - rtnl_route_set_oif (route, iface_idx); - - if (gw && !IN6_IS_ADDR_UNSPECIFIED (gw)) { - /* Build up the gateway address */ - gw_addr = nl_addr_build (AF_INET6, (void *) gw, sizeof (*gw)); - if (!gw_addr) { - err = -ENOMEM; - goto out; - } - nl_addr_set_prefixlen (gw_addr, -1); - rtnl_route_set_gateway (route, gw_addr); - } - /* Add the new default route */ - err = rtnl_route_add (nlh, route, NLM_F_REPLACE); - if (err == -EEXIST) { + nm_netlink_route_add(route, AF_INET6, NULL, 0, gw, NLM_F_REPLACE); + if (err == -NLE_EXIST) { /* FIXME: even though we use NLM_F_REPLACE the kernel won't replace * the route if it's the same. Should try to remove it first, then * add the new one again here. @@ -1134,9 +1009,6 @@ replace_default_ip6_route (const char *iface, const struct in6_addr *gw) err = 0; } -out: - if (gw_addr) - nl_addr_put (gw_addr); rtnl_route_put (route); return err; } @@ -1148,20 +1020,20 @@ out: * */ gboolean -nm_system_replace_default_ip6_route (const char *iface, const struct in6_addr *gw) +nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw) { struct rtnl_route *gw_route = NULL; - struct nl_handle *nlh; gboolean success = FALSE; + const char *iface; int err; - nlh = nm_netlink_get_default_handle (); - g_return_val_if_fail (nlh != NULL, FALSE); + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); - err = replace_default_ip6_route (iface, gw); - if (err == 0) { + err = replace_default_ip6_route (ifindex, gw); + if (err == 0) return TRUE; - } else if (err != -ESRCH) { + if (err != -NLE_OBJ_NOTFOUND) { nm_log_err (LOGD_DEVICE | LOGD_IP6, "(%s): failed to set IPv6 default route: %d", iface, err); @@ -1169,14 +1041,14 @@ nm_system_replace_default_ip6_route (const char *iface, const struct in6_addr *g } /* Try adding a direct route to the gateway first */ - gw_route = add_ip6_route_to_gateway (iface, gw); + gw_route = add_ip6_route_to_gateway (ifindex, gw); if (!gw_route) return FALSE; /* Try adding the original route again */ - err = replace_default_ip6_route (iface, gw); + err = replace_default_ip6_route (ifindex, gw); if (err != 0) { - rtnl_route_del (nlh, gw_route, 0); + nm_netlink_route_delete (gw_route); nm_log_err (LOGD_DEVICE | LOGD_IP6, "(%s): failed to set IPv6 default route (pass #2): %d", iface, err); @@ -1187,169 +1059,55 @@ nm_system_replace_default_ip6_route (const char *iface, const struct in6_addr *g return success; } -static void flush_addresses (const char *iface, int family) -{ - int iface_idx; - - g_return_if_fail (iface != NULL); - iface_idx = nm_netlink_iface_to_index (iface); - if (iface_idx >= 0) - sync_addresses (iface, iface_idx, family, NULL, 0); -} - -/* - * nm_system_device_flush_addresses - * - * Flush all network addresses associated with a network device - * - */ -void nm_system_device_flush_addresses (NMDevice *dev, int family) -{ - g_return_if_fail (dev != NULL); - - flush_addresses (nm_device_get_ip_iface (dev), family); -} - - /* - * nm_system_device_flush_addresses_with_iface + * nm_system_iface_flush_addresses * * Flush all network addresses associated with a network device * */ -void nm_system_device_flush_addresses_with_iface (const char *iface) -{ - flush_addresses (iface, AF_UNSPEC); -} - - -static void -foreach_route (void (*callback)(struct nl_object *, gpointer), - gpointer user_data) -{ - struct nl_handle *nlh; - struct nl_cache *route_cache; - - nlh = nm_netlink_get_default_handle (); - route_cache = rtnl_route_alloc_cache (nlh); - g_assert (route_cache); - nl_cache_foreach (route_cache, callback, user_data); - nl_cache_free (route_cache); -} - -static void -dump_route (struct rtnl_route *route) +gboolean +nm_system_iface_flush_addresses (int ifindex, int family) { - char buf6[INET6_ADDRSTRLEN]; - char buf4[INET_ADDRSTRLEN]; - struct nl_addr *nl; - struct in6_addr *addr6 = NULL; - struct in_addr *addr4 = NULL; - int prefixlen = 0; - const char *sf = "UNSPEC"; - int family = rtnl_route_get_family (route); - - memset (buf6, 0, sizeof (buf6)); - memset (buf4, 0, sizeof (buf4)); - nl = rtnl_route_get_dst (route); - if (nl) { - if (nl_addr_get_family (nl) == AF_INET) { - addr4 = nl_addr_get_binary_addr (nl); - if (addr4) - inet_ntop (AF_INET, addr4, &buf4[0], sizeof (buf4)); - } else if (nl_addr_get_family (nl) == AF_INET6) { - addr6 = nl_addr_get_binary_addr (nl); - if (addr6) - inet_ntop (AF_INET6, addr6, &buf6[0], sizeof (buf6)); - } - prefixlen = nl_addr_get_prefixlen (nl); - } - - if (family == AF_INET) - sf = "INET"; - else if (family == AF_INET6) - sf = "INET6"; - - nm_log_dbg (LOGD_IP4 | LOGD_IP6, " route idx %d family %s (%d) addr %s/%d", - rtnl_route_get_oif (route), - sf, family, - strlen (buf4) ? buf4 : (strlen (buf6) ? buf6 : "<unknown>"), - prefixlen); + g_return_val_if_fail (ifindex > 0, FALSE); + return sync_addresses (ifindex, family, NULL, 0); } -typedef struct { - const char *iface; - int iface_idx; - int family; -} RouteCheckData; -static void -check_one_route (struct nl_object *object, void *user_data) +static struct rtnl_route * +delete_one_route (struct rtnl_route *route, + struct nl_addr *dst, + const char *iface, + gpointer user_data) { - RouteCheckData *data = (RouteCheckData *) user_data; - struct rtnl_route *route = (struct rtnl_route *) object; - int err; - guint32 log_level = LOGD_IP4 | LOGD_IP6; - - if (nm_logging_level_enabled (LOGL_DEBUG)) - dump_route (route); + guint32 log_level = GPOINTER_TO_UINT (user_data); - /* Delete all routes from this interface */ - if (rtnl_route_get_oif (route) != data->iface_idx) - return; - if (data->family && rtnl_route_get_family (route) != data->family) - return; - - /* We don't want to flush IPv6 link-local routes that may exist on the - * the interface since the LL address and routes should normally stay - * assigned all the time. - */ - if ( (data->family == AF_INET6 || data->family == AF_UNSPEC) - && (rtnl_route_get_family (route) == AF_INET6)) { - struct nl_addr *nl; - struct in6_addr *addr = NULL; - - nl = rtnl_route_get_dst (route); - if (nl) - addr = nl_addr_get_binary_addr (nl); - - if (addr) { - if ( IN6_IS_ADDR_LINKLOCAL (addr) - || IN6_IS_ADDR_MC_LINKLOCAL (addr) - || (IN6_IS_ADDR_MULTICAST (addr) && (nl_addr_get_prefixlen (nl) == 8))) - return; - } - } - - if (data->family == AF_INET) - log_level = LOGD_IP4; - else if (data->family == AF_INET6) - log_level = LOGD_IP6; nm_log_dbg (log_level, " deleting route"); + if (!nm_netlink_route_delete (route)) + nm_log_err (LOGD_DEVICE, "(%s): failed to delete route", iface); - err = rtnl_route_del (nm_netlink_get_default_handle (), route, 0); - if (err < 0 && (err != -ERANGE)) { - nm_log_err (LOGD_DEVICE, - "(%s): error %d returned from rtnl_route_del(): %s", - data->iface, err, nl_geterror ()); - } + return NULL; } -static void flush_routes (int ifindex, const char *iface, int family) +/** + * nm_system_iface_flush_routes: + * @ifindex: interface index + * @family: address family, i.e. AF_INET, AF_INET6, or AF_UNSPEC + * + * Flush all network addresses associated with a network device. + * + * Returns: %TRUE on success, %FALSE on failure + **/ +gboolean +nm_system_iface_flush_routes (int ifindex, int family) { - RouteCheckData check_data; guint32 log_level = LOGD_IP4 | LOGD_IP6; const char *sf = "UNSPEC"; + const char *iface; - g_return_if_fail (iface != NULL); + g_return_val_if_fail (ifindex > 0, FALSE); - if (ifindex < 0) { - ifindex = nm_netlink_iface_to_index (iface); - if (ifindex < 0) { - nm_log_dbg (LOGD_DEVICE, "(%s) failed to lookup interface index", iface); - return; - } - } + iface = nm_netlink_index_to_iface (ifindex); + g_return_val_if_fail (iface != NULL, FALSE); if (family == AF_INET) { log_level = LOGD_IP4; @@ -1361,104 +1119,59 @@ static void flush_routes (int ifindex, const char *iface, int family) nm_log_dbg (log_level, "(%s): flushing routes ifindex %d family %s (%d)", iface, ifindex, sf, family); - memset (&check_data, 0, sizeof (check_data)); - check_data.iface = iface; - check_data.iface_idx = ifindex; - check_data.family = family; - foreach_route (check_one_route, &check_data); -} - -/* - * nm_system_device_flush_routes - * - * Flush all network addresses associated with a network device - * - */ -void nm_system_device_flush_routes (NMDevice *dev, int family) -{ - g_return_if_fail (dev != NULL); - - flush_routes (nm_device_get_ip_ifindex (dev), - nm_device_get_ip_iface (dev), - family); -} - -/* - * nm_system_device_flush_routes_with_iface - * - * Flush all routes associated with a network device. 'family' is an - * address family, either AF_INET, AF_INET6, or AF_UNSPEC. - * - */ -void nm_system_device_flush_routes_with_iface (const char *iface, int family) -{ - flush_routes (-1, iface, family); + /* We don't want to flush IPv6 link-local routes that may exist on the + * the interface since the LL address and routes should normally stay + * assigned all the time. + */ + nm_netlink_foreach_route (ifindex, family, RT_SCOPE_UNIVERSE, TRUE, delete_one_route, GUINT_TO_POINTER (log_level)); + return TRUE; } -typedef struct { - struct rtnl_route *route; - NMIP4Config *config; - int iface; -} SetPriorityInfo; - -static void -find_route (struct nl_object *object, gpointer user_data) +static struct rtnl_route * +find_route (struct rtnl_route *route, + struct nl_addr *dst, + const char *iface, + gpointer user_data) { - struct rtnl_route *route = (struct rtnl_route *) object; - SetPriorityInfo *info = (SetPriorityInfo *) user_data; - struct nl_addr *dst; + NMIP4Config *config = user_data; struct in_addr *dst_addr; int num; int i; - if (info->route || - rtnl_route_get_oif (route) != info->iface || - rtnl_route_get_scope (route) != RT_SCOPE_LINK) - return; - - dst = rtnl_route_get_dst (route); - if (nl_addr_get_family (dst) != AF_INET) - return; + if (dst && (nl_addr_get_family (dst) != AF_INET)) + return NULL; + /* Find the first route that handles a subnet of at least one of the + * device's IPv4 addresses. + */ dst_addr = nl_addr_get_binary_addr (dst); - num = nm_ip4_config_get_num_addresses (info->config); + num = nm_ip4_config_get_num_addresses (config); for (i = 0; i < num; i++) { - NMIP4Address *addr = nm_ip4_config_get_address (info->config, i); + NMIP4Address *addr = nm_ip4_config_get_address (config, i); guint32 prefix = nm_ip4_address_get_prefix (addr); guint32 address = nm_ip4_address_get_address (addr); - if (prefix == nl_addr_get_prefixlen (dst) && - (address & nm_utils_ip4_prefix_to_netmask (prefix)) == dst_addr->s_addr) { - - /* Ref the route so it sticks around after the cache is cleared */ - rtnl_route_get (route); - info->route = route; - break; - } + if ( prefix == nl_addr_get_prefixlen (dst) + && (address & nm_utils_ip4_prefix_to_netmask (prefix)) == dst_addr->s_addr) + return route; } + return NULL; } static void -nm_system_device_set_priority (const char *iface, - NMIP4Config *config, - int priority) +nm_system_device_set_priority (int ifindex, + NMIP4Config *config, + int priority) { - SetPriorityInfo info; - - info.route = NULL; - info.config = config; - info.iface = nm_netlink_iface_to_index (iface); - g_return_if_fail (info.iface >= 0); - - foreach_route (find_route, &info); - if (info.route) { - struct nl_handle *nlh; + struct nl_sock *nlh; + struct rtnl_route *found; + found = nm_netlink_foreach_route (ifindex, AF_INET, RT_SCOPE_LINK, FALSE, find_route, config); + if (found) { nlh = nm_netlink_get_default_handle (); - rtnl_route_del (nlh, info.route, 0); - - rtnl_route_set_prio (info.route, priority); - rtnl_route_add (nlh, info.route, 0); - rtnl_route_put (info.route); + nm_netlink_route_delete (found); + rtnl_route_set_priority (found, priority); + rtnl_route_add (nlh, found, 0); + rtnl_route_put (found); } } diff --git a/src/nm-system.h b/src/nm-system.h index 094f40ef..ae4e7d91 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -35,33 +35,31 @@ * implemented in the backend files in backends/ directory */ -void nm_system_device_flush_routes (NMDevice *dev, int family); -void nm_system_device_flush_routes_with_iface (const char *iface, int family); +gboolean nm_system_iface_flush_routes (int ifindex, int family); -gboolean nm_system_replace_default_ip4_route (const char *iface, +gboolean nm_system_replace_default_ip4_route (int ifindex, guint32 gw, guint32 mss); -gboolean nm_system_replace_default_ip6_route (const char *iface, +gboolean nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw); -gboolean nm_system_replace_default_ip4_route_vpn (const char *iface, +gboolean nm_system_replace_default_ip4_route_vpn (int ifindex, guint32 ext_gw, guint32 int_gw, guint32 mss, - const char *parent_iface, + int parent_ifindex, guint32 parent_mss); struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config); -void nm_system_device_flush_addresses (NMDevice *dev, int family); -void nm_system_device_flush_addresses_with_iface (const char *iface); +gboolean nm_system_iface_flush_addresses (int ifindex, int family); void nm_system_enable_loopback (void); void nm_system_update_dns (void); -gboolean nm_system_apply_ip4_config (const char *iface, +gboolean nm_system_apply_ip4_config (int ifindex, NMIP4Config *config, int priority, NMIP4ConfigCompareFlags flags); @@ -76,22 +74,19 @@ int nm_system_set_ip6_route (int ifindex, int table, struct rtnl_route **out_route); -gboolean nm_system_apply_ip6_config (const char *iface, +gboolean nm_system_apply_ip6_config (int ifindex, NMIP6Config *config, int priority, NMIP6ConfigCompareFlags flags); -gboolean nm_system_device_set_up_down (NMDevice *dev, - gboolean up, - gboolean *no_firmware); -gboolean nm_system_device_set_up_down_with_iface (const char *iface, - gboolean up, - gboolean *no_firmware); +gboolean nm_system_iface_set_up (int ifindex, + gboolean up, + gboolean *no_firmware); -gboolean nm_system_device_is_up (NMDevice *device); -gboolean nm_system_device_is_up_with_iface (const char *iface); +gboolean nm_system_iface_is_up (int ifindex); -gboolean nm_system_device_set_mtu (const char *iface, guint32 mtu); -gboolean nm_system_device_set_mac (const char *iface, const struct ether_addr *mac); +gboolean nm_system_iface_set_mtu (int ifindex, guint32 mtu); + +gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac); #endif diff --git a/src/nm-wifi-ap.c b/src/nm-wifi-ap.c index f9c66473..93d012fb 100644 --- a/src/nm-wifi-ap.c +++ b/src/nm-wifi-ap.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2004 - 2010 Red Hat, Inc. + * Copyright (C) 2004 - 2011 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -59,10 +59,6 @@ typedef struct gboolean fake; /* Whether or not the AP is from a scan */ gboolean broadcast; /* Whether or not the AP is broadcasting (hidden) */ glong last_seen; /* Last time the AP was seen in a scan in seconds */ - - /* Things from user prefs/NetworkManagerInfo */ - GTimeVal timestamp; - GSList * user_addresses; } NMAccessPointPrivate; #define NM_AP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP, NMAccessPointPrivate)) @@ -112,8 +108,6 @@ finalize (GObject *object) g_free (priv->dbus_path); if (priv->ssid) g_byte_array_free (priv->ssid, TRUE); - g_slist_foreach (priv->user_addresses, (GFunc)g_free, NULL); - g_slist_free (priv->user_addresses); G_OBJECT_CLASS (nm_ap_parent_class)->finalize (object); } @@ -773,7 +767,6 @@ nm_ap_print_self (NMAccessPoint *ap, ap); nm_log_dbg (LOGD_WIFI_SCAN, " BSSID " MAC_FMT, MAC_ARG (priv->address.ether_addr_octet)); nm_log_dbg (LOGD_WIFI_SCAN, " mode %d", priv->mode); - nm_log_dbg (LOGD_WIFI_SCAN, " timestamp %ld", priv->timestamp.tv_sec); nm_log_dbg (LOGD_WIFI_SCAN, " flags 0x%X", priv->flags); nm_log_dbg (LOGD_WIFI_SCAN, " wpa flags 0x%X", priv->wpa_flags); nm_log_dbg (LOGD_WIFI_SCAN, " rsn flags 0x%X", priv->rsn_flags); @@ -791,37 +784,6 @@ nm_ap_get_dbus_path (NMAccessPoint *ap) return NM_AP_GET_PRIVATE (ap)->dbus_path; } - -/* - * Get/set functions for timestamp - * - */ -const GTimeVal *nm_ap_get_timestamp (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), 0); - - return (&NM_AP_GET_PRIVATE (ap)->timestamp); -} - -void nm_ap_set_timestamp (NMAccessPoint *ap, glong sec, glong usec) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - priv->timestamp.tv_sec = sec; - priv->timestamp.tv_usec = usec; -} - -void nm_ap_set_timestamp_via_timestamp (NMAccessPoint *ap, const GTimeVal *timestamp) -{ - g_return_if_fail (NM_IS_AP (ap)); - - NM_AP_GET_PRIVATE (ap)->timestamp = *timestamp; -} - /* * Get/set functions for ssid * @@ -1151,57 +1113,6 @@ void nm_ap_set_last_seen (NMAccessPoint *ap, const glong last_seen) NM_AP_GET_PRIVATE (ap)->last_seen = last_seen; } - -/* - * Get/Set functions for user address list - * - * The internal address list is always "owned" by the AP and - * the list returned by nm_ap_get_user_addresses() is a deep copy. - * Likewise, when setting the list, a deep copy is made for the - * ap's actual list. - * - */ -GSList *nm_ap_get_user_addresses (const NMAccessPoint *ap) -{ - GSList *new = NULL; - GSList *elt = NULL; - - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - for (elt = NM_AP_GET_PRIVATE (ap)->user_addresses; elt; elt = g_slist_next (elt)) - { - if (elt->data) - new = g_slist_append (new, g_strdup (elt->data)); - } - - /* Return a _deep__copy_ of the address list */ - return new; -} - -void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list) -{ - NMAccessPointPrivate *priv; - GSList *elt = NULL; - GSList *new = NULL; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - /* Free existing list */ - g_slist_foreach (priv->user_addresses, (GFunc) g_free, NULL); - - /* Copy new list and set as our own */ - for (elt = list; elt; elt = g_slist_next (elt)) - { - if (elt->data) - new = g_slist_append (new, g_ascii_strup (elt->data, -1)); - } - - priv->user_addresses = new; -} - - gboolean nm_ap_check_compatible (NMAccessPoint *self, NMConnection *connection) diff --git a/src/nm-wifi-ap.h b/src/nm-wifi-ap.h index 95514ba6..61e5b3b2 100644 --- a/src/nm-wifi-ap.h +++ b/src/nm-wifi-ap.h @@ -24,7 +24,6 @@ #include <glib.h> #include <glib-object.h> -#include <time.h> #include "NetworkManager.h" #include "nm-connection.h" @@ -64,9 +63,6 @@ NMAccessPoint * nm_ap_new_fake_from_connection (NMConnection *connection); void nm_ap_export_to_dbus (NMAccessPoint *ap); const char * nm_ap_get_dbus_path (NMAccessPoint *ap); -const GTimeVal * nm_ap_get_timestamp (const NMAccessPoint *ap); -void nm_ap_set_timestamp (NMAccessPoint *ap, glong sec, glong usec); -void nm_ap_set_timestamp_via_timestamp (NMAccessPoint *ap, const GTimeVal *timestamp); const GByteArray * nm_ap_get_ssid (const NMAccessPoint * ap); void nm_ap_set_ssid (NMAccessPoint * ap, const GByteArray * ssid); @@ -104,9 +100,6 @@ void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast); glong nm_ap_get_last_seen (const NMAccessPoint *ap); void nm_ap_set_last_seen (NMAccessPoint *ap, const glong last_seen); -GSList * nm_ap_get_user_addresses (const NMAccessPoint *ap); -void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list); - gboolean nm_ap_check_compatible (NMAccessPoint *self, NMConnection *connection); diff --git a/src/ppp-manager/Makefile.in b/src/ppp-manager/Makefile.in index 13c60b41..0f0f6ab5 100644 --- a/src/ppp-manager/Makefile.in +++ b/src/ppp-manager/Makefile.in @@ -222,6 +222,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index e863aaba..522c0751 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -875,6 +875,8 @@ create_pppd_cmd_line (NMPPPManager *self, nm_cmd_line_add_string (cmd, "refuse-mschap-v2"); if (nm_setting_ppp_get_nobsdcomp (setting)) nm_cmd_line_add_string (cmd, "nobsdcomp"); + if (nm_setting_ppp_get_no_vj_comp (setting)) + nm_cmd_line_add_string (cmd, "novj"); if (nm_setting_ppp_get_nodeflate (setting)) nm_cmd_line_add_string (cmd, "nodeflate"); if (nm_setting_ppp_get_require_mppe (setting)) diff --git a/src/settings/Makefile.in b/src/settings/Makefile.in index 980f35cb..b12742f0 100644 --- a/src/settings/Makefile.in +++ b/src/settings/Makefile.in @@ -248,6 +248,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 4b3a56cd..6a208529 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -84,15 +84,27 @@ typedef struct { NMDBusManager *dbus_mgr; NMAgentManager *agent_mgr; + NMSessionMonitor *session_monitor; + guint session_changed_id; GSList *pending_auths; /* List of pending authentication requests */ - NMConnection *secrets; gboolean visible; /* Is this connection is visible by some session? */ - GSList *reqs; /* in-progress secrets requests */ - NMSessionMonitor *session_monitor; - guint session_changed_id; + /* Caches secrets from on-disk connections; were they not cached any + * call to nm_connection_clear_secrets() wipes them out and we'd have + * to re-read them from disk which defeats the purpose of having the + * connection in-memory at all. + */ + NMConnection *system_secrets; + + /* Caches secrets from agents during the activation process; if new system + * secrets are returned from an agent, they get written out to disk, + * triggering a re-read of the connection, which reads only system + * secrets, and would wipe out any agent-owned or not-saved secrets the + * agent also returned. + */ + NMConnection *agent_secrets; guint64 timestamp; /* Up-to-date timestamp of connection use */ GHashTable *seen_bssids; /* Up-to-date BSSIDs that's been seen for the connection */ @@ -294,57 +306,67 @@ nm_settings_connection_check_permission (NMSettingsConnection *self, /**************************************************************/ -static void -only_system_secrets_cb (NMSetting *setting, - const char *key, - const GValue *value, - GParamFlags flags, - gpointer user_data) +static gboolean +secrets_filter_cb (NMSetting *setting, + const char *secret, + NMSettingSecretFlags flags, + gpointer user_data) { - if (flags & NM_SETTING_PARAM_SECRET) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + NMSettingSecretFlags filter_flags = GPOINTER_TO_UINT (user_data); - /* VPNs are special; need to handle each secret separately */ - if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) { - GHashTableIter iter; - const char *secret_name = NULL; + /* Returns TRUE to remove the secret */ - g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value)); - while (g_hash_table_iter_next (&iter, (gpointer *) &secret_name, NULL)) { - secret_flags = NM_SETTING_SECRET_FLAG_NONE; - nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL); - if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) - nm_setting_vpn_remove_secret (NM_SETTING_VPN (setting), secret_name); - } - } else { - nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); - if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) - g_object_set (G_OBJECT (setting), key, NULL, NULL); - } - } + /* Can't use bitops with SECRET_FLAG_NONE so handle that specifically */ + if ( (flags == NM_SETTING_SECRET_FLAG_NONE) + && (filter_flags == NM_SETTING_SECRET_FLAG_NONE)) + return FALSE; + + /* Otherwise if the secret has at least one of the desired flags keep it */ + return (flags & filter_flags) ? FALSE : TRUE; } static void -update_secrets_cache (NMSettingsConnection *self) +update_system_secrets_cache (NMSettingsConnection *self) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - if (priv->secrets) - g_object_unref (priv->secrets); - priv->secrets = nm_connection_duplicate (NM_CONNECTION (self)); + if (priv->system_secrets) + g_object_unref (priv->system_secrets); + priv->system_secrets = nm_connection_duplicate (NM_CONNECTION (self)); /* Clear out non-system-owned and not-saved secrets */ - nm_connection_for_each_setting_value (priv->secrets, only_system_secrets_cb, NULL); + nm_connection_clear_secrets_with_flags (priv->system_secrets, + secrets_filter_cb, + GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_NONE)); } -static gboolean -clear_system_secrets (GHashTableIter *iter, - NMSettingSecretFlags flags, - gpointer user_data) +static void +update_agent_secrets_cache (NMSettingsConnection *self, NMConnection *new) { - if (flags == NM_SETTING_SECRET_FLAG_NONE) - g_hash_table_iter_remove (iter); - return TRUE; + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + NMSettingSecretFlags filter_flags = NM_SETTING_SECRET_FLAG_NOT_SAVED | NM_SETTING_SECRET_FLAG_AGENT_OWNED; + + if (priv->agent_secrets) + g_object_unref (priv->agent_secrets); + priv->agent_secrets = nm_connection_duplicate (new ? new : NM_CONNECTION (self)); + + /* Clear out non-system-owned secrets */ + nm_connection_clear_secrets_with_flags (priv->agent_secrets, + secrets_filter_cb, + GUINT_TO_POINTER (filter_flags)); +} + +static void +secrets_cleared_cb (NMSettingsConnection *self) +{ + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + + /* Clear agent secrets when connection's secrets are cleared since agent + * secrets are transient. + */ + if (priv->agent_secrets) + g_object_unref (priv->agent_secrets); + priv->agent_secrets = NULL; } /* Update the settings of this connection to match that of 'new', taking care to @@ -356,7 +378,7 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, GError **error) { NMSettingsConnectionPrivate *priv; - GHashTable *new_settings, *transient_secrets; + GHashTable *new_settings, *hash = NULL; gboolean success = FALSE; g_return_val_if_fail (self != NULL, FALSE); @@ -366,37 +388,29 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - /* Replacing the settings might replace transient secrets, such as when - * a user agent returns secrets, which might trigger the connection to be - * written out, which triggers an inotify event to re-read and update the - * connection, which, if we're not careful, could wipe out the transient - * secrets the user agent just sent us. Basically, only - * nm_connection_clear_secrets() should wipe out transient secrets but - * re-reading a connection from on-disk and updating our in-memory copy - * should not. Thus we preserve non-system-owned secrets here. - */ - transient_secrets = nm_connection_to_hash (NM_CONNECTION (self), NM_SETTING_HASH_FLAG_ONLY_SECRETS); - if (transient_secrets) - for_each_secret (NM_CONNECTION (self), transient_secrets, clear_system_secrets, NULL); - new_settings = nm_connection_to_hash (new, NM_SETTING_HASH_FLAG_ALL); g_assert (new_settings); if (nm_connection_replace_settings (NM_CONNECTION (self), new_settings, error)) { - /* Copy the connection to keep its secrets around even if NM - * calls nm_connection_clear_secrets(). + /* Cache the just-updated system secrets in case something calls + * nm_connection_clear_secrets() and clears them. */ - update_secrets_cache (self); + update_system_secrets_cache (self); + success = TRUE; - /* And add the transient secrets back */ - if (transient_secrets) - nm_connection_update_secrets (NM_CONNECTION (self), NULL, transient_secrets, NULL); + /* Add agent and always-ask secrets back; they won't necessarily be + * in the replacement connection data if it was eg reread from disk. + */ + if (priv->agent_secrets) { + hash = nm_connection_to_hash (priv->agent_secrets, NM_SETTING_HASH_FLAG_ONLY_SECRETS); + if (hash) { + success = nm_connection_update_secrets (NM_CONNECTION (self), NULL, hash, error); + g_hash_table_destroy (hash); + } + } nm_settings_connection_recheck_visibility (self); - success = TRUE; } g_hash_table_destroy (new_settings); - if (transient_secrets) - g_hash_table_destroy (transient_secrets); return success; } @@ -719,7 +733,7 @@ agent_secrets_done_cb (NMAgentManager *manager, /* Update the connection with our existing secrets from backing storage */ nm_connection_clear_secrets (NM_CONNECTION (self)); - hash = nm_connection_to_hash (priv->secrets, NM_SETTING_HASH_FLAG_ONLY_SECRETS); + hash = nm_connection_to_hash (priv->system_secrets, NM_SETTING_HASH_FLAG_ONLY_SECRETS); if (!hash || nm_connection_update_secrets (NM_CONNECTION (self), setting_name, hash, &local)) { /* Update the connection with the agent's secrets; by this point if any * system-owned secrets exist in 'secrets' the agent that provided them @@ -730,7 +744,8 @@ agent_secrets_done_cb (NMAgentManager *manager, /* Now that all secrets are updated, copy and cache new secrets, * then save them to backing storage. */ - update_secrets_cache (self); + update_system_secrets_cache (self); + update_agent_secrets_cache (self, NULL); /* Only save secrets to backing storage if the agent returned any * new system secrets. If it didn't, then the secrets are agent- @@ -807,11 +822,9 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self, guint32 call_id = 0; /* Use priv->secrets to work around the fact that nm_connection_clear_secrets() - * will clear secrets on this object's settings. priv->secrets should be - * a complete copy of this object and kept in sync by - * nm_settings_connection_replace_settings(). + * will clear secrets on this object's settings. */ - if (!priv->secrets) { + if (!priv->system_secrets) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "%s.%d - Internal error; secrets cache invalid.", __FILE__, __LINE__); @@ -826,7 +839,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self, return 0; } - existing_secrets = nm_connection_to_hash (priv->secrets, NM_SETTING_HASH_FLAG_ONLY_SECRETS); + existing_secrets = nm_connection_to_hash (priv->system_secrets, NM_SETTING_HASH_FLAG_ONLY_SECRETS); call_id = nm_agent_manager_get_secrets (priv->agent_mgr, NM_CONNECTION (self), filter_by_uid, @@ -1084,47 +1097,40 @@ impl_settings_connection_get_settings (NMSettingsConnection *self, auth_start (self, context, NULL, get_settings_auth_cb, NULL); } +typedef struct { + DBusGMethodInvocation *context; + NMAgentManager *agent_mgr; + gulong sender_uid; +} UpdateInfo; + static void -con_update_cb (NMSettingsConnection *connection, +con_update_cb (NMSettingsConnection *self, GError *error, gpointer user_data) { - DBusGMethodInvocation *context = user_data; + UpdateInfo *info = user_data; + NMConnection *for_agent; if (error) - dbus_g_method_return_error (context, error); - else - dbus_g_method_return (context); -} - -static void -secrets_filter_cb (NMSetting *setting, - const char *key, - const GValue *value, - GParamFlags flags, - gpointer user_data) -{ - NMSettingSecretFlags filter_flags = GPOINTER_TO_UINT (user_data); - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - const char *secret_name = NULL; - GHashTableIter iter; + dbus_g_method_return_error (info->context, error); + else { + /* Dupe the connection so we can clear out non-agent-owned secrets, + * as agent-owned secrets are the only ones we send back be saved. + * Only send secrets to agents of the same UID that called update too. + */ + for_agent = nm_connection_duplicate (NM_CONNECTION (self)); + nm_connection_clear_secrets_with_flags (for_agent, + secrets_filter_cb, + GUINT_TO_POINTER (NM_SETTING_SECRET_FLAG_AGENT_OWNED)); + nm_agent_manager_save_secrets (info->agent_mgr, for_agent, TRUE, info->sender_uid); + g_object_unref (for_agent); - if (flags & NM_SETTING_PARAM_SECRET) { - if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) { - /* VPNs are special; need to handle each secret separately */ - g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value)); - while (g_hash_table_iter_next (&iter, (gpointer) &secret_name, NULL)) { - secret_flags = NM_SETTING_SECRET_FLAG_NONE; - nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL); - if (!(secret_flags & filter_flags)) - nm_setting_vpn_remove_secret (NM_SETTING_VPN (setting), secret_name); - } - } else { - nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); - if (!(secret_flags & filter_flags)) - g_object_set (G_OBJECT (setting), key, NULL, NULL); - } + dbus_g_method_return (info->context); } + + g_object_unref (info->agent_mgr); + memset (info, 0, sizeof (*info)); + g_free (info); } static void @@ -1136,54 +1142,27 @@ update_auth_cb (NMSettingsConnection *self, { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMConnection *new_settings = data; - NMConnection *for_agent, *dup; - NMSettingSecretFlags filter_flags; - GHashTable *hash; - GError *local = NULL; + UpdateInfo *info; if (error) dbus_g_method_return_error (context, error); else { - /* Cache the new secrets since they may get overwritten by the replace - * when transient secrets are copied back. + info = g_malloc0 (sizeof (*info)); + info->context = context; + info->agent_mgr = g_object_ref (priv->agent_mgr); + info->sender_uid = sender_uid; + + /* Cache the new secrets from the agent, as stuff like inotify-triggered + * changes to connection's backing config files will blow them away if + * they're in the main connection. */ - dup = nm_connection_duplicate (new_settings); + update_agent_secrets_cache (self, new_settings); /* Update and commit our settings. */ nm_settings_connection_replace_and_commit (self, - new_settings, - con_update_cb, - context); - - /* Copy new agent secrets back to the connection */ - filter_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED; - nm_connection_for_each_setting_value (dup, - secrets_filter_cb, - GUINT_TO_POINTER (filter_flags)); - hash = nm_connection_to_hash (dup, NM_SETTING_HASH_FLAG_ONLY_SECRETS); - g_object_unref (dup); - - if (hash) { - if (!nm_connection_update_secrets (NM_CONNECTION (self), NULL, hash, &local)) { - nm_log_warn (LOGD_SETTINGS, "Failed to update connection secrets: (%d) %s", - local ? local->code : -1, - local && local->message ? local->message : "(unknown)"); - g_clear_error (&local); - } - g_hash_table_destroy (hash); - } - - /* Dupe the connection and clear out non-agent-owned secrets so we can - * send the agent-owned ones to agents to be saved. Only send them to - * agents of the same UID as the Update() request sender. - */ - for_agent = nm_connection_duplicate (NM_CONNECTION (self)); - filter_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED; - nm_connection_for_each_setting_value (for_agent, - secrets_filter_cb, - GUINT_TO_POINTER (filter_flags)); - nm_agent_manager_save_secrets (priv->agent_mgr, for_agent, TRUE, sender_uid); - g_object_unref (for_agent); + new_settings, + con_update_cb, + info); } g_object_unref (new_settings); @@ -1345,16 +1324,11 @@ dbus_get_agent_secrets_cb (NMSettingsConnection *self, if (error) dbus_g_method_return_error (context, error); else { - /* The connection's secrets will have been updated by the agent manager, - * so we want to refresh the secrets cache. Note that we will never save - * new secrets to backing storage here because D-Bus initated requests will - * never ask for completely new secrets from agents. Thus system-owned - * secrets should not have changed from backing storage. We also don't - * send agent-owned secrets back out to be saved since we assume the agent - * that provided the secrets saved them itself. + /* Return secrets from agent and backing storage to the D-Bus caller; + * nm_settings_connection_get_secrets() will have updated itself with + * secrets from backing storage and those returned from the agent + * by the time we get here. */ - update_secrets_cache (self); - hash = nm_connection_to_hash (NM_CONNECTION (self), NM_SETTING_HASH_FLAG_ONLY_SECRETS); if (!hash) hash = g_hash_table_new (NULL, NULL); @@ -1726,6 +1700,8 @@ nm_settings_connection_init (NMSettingsConnection *self) priv->agent_mgr = nm_agent_manager_get (); priv->seen_bssids = g_hash_table_new_full (mac_hash, mac_equal, g_free, g_free); + + g_signal_connect (self, "secrets-cleared", G_CALLBACK (secrets_cleared_cb), NULL); } static void @@ -1739,8 +1715,10 @@ dispose (GObject *object) goto out; priv->disposed = TRUE; - if (priv->secrets) - g_object_unref (priv->secrets); + if (priv->system_secrets) + g_object_unref (priv->system_secrets); + if (priv->agent_secrets) + g_object_unref (priv->agent_secrets); /* Cancel PolicyKit requests */ for (iter = priv->pending_auths; iter; iter = g_slist_next (iter)) diff --git a/src/settings/plugins/Makefile.in b/src/settings/plugins/Makefile.in index 148e9620..f22610dd 100644 --- a/src/settings/plugins/Makefile.in +++ b/src/settings/plugins/Makefile.in @@ -197,6 +197,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifcfg-rh/Makefile.in b/src/settings/plugins/ifcfg-rh/Makefile.in index f02b6431..1a2e9b77 100644 --- a/src/settings/plugins/ifcfg-rh/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/Makefile.in @@ -267,6 +267,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index ed0dceca..b4be4cba 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -655,8 +655,10 @@ sc_plugin_ifcfg_init (SCPluginIfcfg *plugin) } if (!success) { - dbus_g_connection_unref (priv->bus); - priv->bus = NULL; + if (priv->bus) { + dbus_g_connection_unref (priv->bus); + priv->bus = NULL; + } } } diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/Makefile.in index cd37d0a7..fa0298a4 100644 --- a/src/settings/plugins/ifcfg-rh/tests/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.in @@ -228,6 +228,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in index a10cbb86..087768e4 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in @@ -152,6 +152,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifcfg-suse/Makefile.in b/src/settings/plugins/ifcfg-suse/Makefile.in index 02e2247a..8c1ab0fd 100644 --- a/src/settings/plugins/ifcfg-suse/Makefile.in +++ b/src/settings/plugins/ifcfg-suse/Makefile.in @@ -215,6 +215,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifnet/Makefile.in b/src/settings/plugins/ifnet/Makefile.in index 2bc7bc32..4f50be2e 100644 --- a/src/settings/plugins/ifnet/Makefile.in +++ b/src/settings/plugins/ifnet/Makefile.in @@ -263,6 +263,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c index 982f94f9..b4aaa8d2 100644 --- a/src/settings/plugins/ifnet/connection_parser.c +++ b/src/settings/plugins/ifnet/connection_parser.c @@ -1742,27 +1742,27 @@ ifnet_update_connection_from_config_block (const char *conn_name, GError **error /* IPv4 setting */ make_ip4_setting (connection, conn_name, error); - if (error && *error) - PLUGIN_WARN (IFNET_PLUGIN_NAME, - "Found error: %s", (*error)->message); + if (error && *error) { + PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s", (*error)->message); + goto error; + } /* IPv6 setting */ make_ip6_setting (connection, conn_name, error); - if (error && *error) - PLUGIN_WARN (IFNET_PLUGIN_NAME, - "Found error: %s", (*error)->message); + if (error && *error) { + PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s", (*error)->message); + goto error; + } success = nm_connection_verify (connection, error); if (error && *error) - PLUGIN_WARN (IFNET_PLUGIN_NAME, - "Found error: %s", (*error)->message); + PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s", (*error)->message); PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Connection verified %s:%d", conn_name, success); if (!success) goto error; return connection; error: - g_object_unref (setting); g_object_unref (connection); return NULL; } diff --git a/src/settings/plugins/ifnet/tests/Makefile.in b/src/settings/plugins/ifnet/tests/Makefile.in index 17b80c36..8ed45a66 100644 --- a/src/settings/plugins/ifnet/tests/Makefile.in +++ b/src/settings/plugins/ifnet/tests/Makefile.in @@ -186,6 +186,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifnet/tests/net b/src/settings/plugins/ifnet/tests/net index e7550002..0eef399a 100644 --- a/src/settings/plugins/ifnet/tests/net +++ b/src/settings/plugins/ifnet/tests/net @@ -35,6 +35,8 @@ config_eth6=("192.168.4.{1..101}/24") config_eth7=( "dhcp" ) auto_eth7="true" +# missing config_eth8 +auto_eth8="true" config_myxjtu2=("202.117.16.121/24 brd 202.117.16.255") routes_myxjtu2=("default via 202.117.16.1") diff --git a/src/settings/plugins/ifnet/tests/test_all.c b/src/settings/plugins/ifnet/tests/test_all.c index d114bbba..52d9ce2a 100644 --- a/src/settings/plugins/ifnet/tests/test_all.c +++ b/src/settings/plugins/ifnet/tests/test_all.c @@ -252,25 +252,25 @@ test_is_unmanaged () static void test_new_connection () { - GError **error = NULL; + GError *error = NULL; NMConnection *connection; - connection = ifnet_update_connection_from_config_block ("eth2", error); + connection = ifnet_update_connection_from_config_block ("eth2", &error); ASSERT (connection != NULL, "new connection", "new connection failed: %s", - error == NULL ? "None" : (*error)->message); + error ? error->message : "None"); g_object_unref (connection); - connection = - ifnet_update_connection_from_config_block ("qiaomuf", error); + + connection = ifnet_update_connection_from_config_block ("qiaomuf", &error); ASSERT (connection != NULL, "new connection", - "new connection failed: %s", error - && (*error) ? (*error)->message : "NONE"); + "new connection failed: %s", + error ? error->message : "NONE"); g_object_unref (connection); - connection = - ifnet_update_connection_from_config_block ("myxjtu2", error); + + connection = ifnet_update_connection_from_config_block ("myxjtu2", &error); ASSERT (connection != NULL, "new connection", - "new connection failed: %s", error - && (*error) ? (*error)->message : "NONE"); + "new connection failed: %s", + error ? error->message : "NONE"); g_object_unref (connection); } @@ -280,32 +280,32 @@ test_new_connection () static void test_update_connection () { - GError **error = NULL; + GError *error = NULL; NMConnection *connection; gboolean success; - connection = ifnet_update_connection_from_config_block ("eth0", error); + connection = ifnet_update_connection_from_config_block ("eth0", &error); ASSERT (connection != NULL, "get connection", "get connection failed: %s", - error == NULL ? "None" : (*error)->message); + error ? error->message : "None"); success = ifnet_update_parsers_by_connection (connection, "eth0", NET_GEN_NAME, SUP_GEN_NAME, NULL, - error); + &error); ASSERT (success, "update connection", "update connection failed %s", "eth0"); g_object_unref (connection); - connection = ifnet_update_connection_from_config_block ("0xab3ace", error); + connection = ifnet_update_connection_from_config_block ("0xab3ace", &error); ASSERT (connection != NULL, "get connection", "get connection failed: %s", - error == NULL ? "None" : (*error)->message); + error ? error->message : "None"); success = ifnet_update_parsers_by_connection (connection, "0xab3ace", NET_GEN_NAME, SUP_GEN_NAME, NULL, - error); + &error); ASSERT (success, "update connection", "update connection failed %s", "0xab3ace"); g_object_unref (connection); @@ -357,6 +357,17 @@ test_delete_connection () } static void +test_missing_config () +{ + GError *error = NULL; + NMConnection *connection; + + connection = ifnet_update_connection_from_config_block ("eth8", &error); + ASSERT (connection == NULL && error != NULL, "get connection", + "get connection should fail with 'Unknown config for eth8'"); +} + +static void run_all (gboolean run) { if (run) { @@ -378,6 +389,7 @@ run_all (gboolean run) test_update_connection (); test_add_connection (); test_delete_connection (); + test_missing_config (); } } diff --git a/src/settings/plugins/ifnet/tests/wpa_supplicant.conf b/src/settings/plugins/ifnet/tests/wpa_supplicant.conf index a2595d42..4f5f68cf 100644 --- a/src/settings/plugins/ifnet/tests/wpa_supplicant.conf +++ b/src/settings/plugins/ifnet/tests/wpa_supplicant.conf @@ -859,6 +859,7 @@ network={ identity="user@example.com" anonymous_identity="anonymous@example.com" password="foobar" - ca_cert="blob://exampleblob" + ca_cert="test_ca_cert.pem" + phase2="auth=CHAP" priority=20 } diff --git a/src/settings/plugins/ifupdown/Makefile.in b/src/settings/plugins/ifupdown/Makefile.in index 5f5a456b..142dcc55 100644 --- a/src/settings/plugins/ifupdown/Makefile.in +++ b/src/settings/plugins/ifupdown/Makefile.in @@ -262,6 +262,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/ifupdown/tests/Makefile.in b/src/settings/plugins/ifupdown/tests/Makefile.in index 7412e65d..1f82564f 100644 --- a/src/settings/plugins/ifupdown/tests/Makefile.in +++ b/src/settings/plugins/ifupdown/tests/Makefile.in @@ -186,6 +186,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/keyfile/Makefile.in b/src/settings/plugins/keyfile/Makefile.in index a2a7d231..c55f22ec 100644 --- a/src/settings/plugins/keyfile/Makefile.in +++ b/src/settings/plugins/keyfile/Makefile.in @@ -238,6 +238,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/keyfile/tests/Makefile.in b/src/settings/plugins/keyfile/tests/Makefile.in index 05ed3a61..7c1ed454 100644 --- a/src/settings/plugins/keyfile/tests/Makefile.in +++ b/src/settings/plugins/keyfile/tests/Makefile.in @@ -224,6 +224,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in index 083615b0..b2c872f5 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in +++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in @@ -152,6 +152,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c index 060093ce..5cfe5a54 100644 --- a/src/settings/plugins/keyfile/writer.c +++ b/src/settings/plugins/keyfile/writer.c @@ -993,15 +993,27 @@ _internal_write_connection (NMConnection *connection, path = g_strdup_printf ("%s/%s-%s", keyfile_dir, filename, nm_connection_get_uuid (connection)); if (g_file_test (path, G_FILE_TEST_EXISTS)) { - /* Hmm, this is odd. Give up. */ - g_set_error (error, KEYFILE_PLUGIN_ERROR, 0, - "%s.%d: could not find suitable keyfile file name (%s already used)", - __FILE__, __LINE__, path); - g_free (path); - goto out; + if (existing_path == NULL || g_strcmp0 (path, existing_path) != 0) { + /* This should not happen. But, it actually occurs when + * two connections have the same UUID, and one of the connections + * is edited to contain the same ID as the other one. + * Give up. + */ + g_set_error (error, KEYFILE_PLUGIN_ERROR, 0, + "%s.%d: could not find suitable keyfile file name (%s already used)", + __FILE__, __LINE__, path); + g_free (path); + goto out; + } } } + /* In case of updating the connection and changing the file path, + * we need to remove the old one, not to end up with two connections. + */ + if (existing_path != NULL && strcmp (path, existing_path) != 0) + unlink (existing_path); + g_file_set_contents (path, data, len, error); if (chown (path, owner_uid, owner_grp) < 0) { g_set_error (error, KEYFILE_PLUGIN_ERROR, 0, diff --git a/src/settings/tests/Makefile.in b/src/settings/tests/Makefile.in index 33c4bd38..c680d008 100644 --- a/src/settings/tests/Makefile.in +++ b/src/settings/tests/Makefile.in @@ -188,6 +188,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/supplicant-manager/Makefile.in b/src/supplicant-manager/Makefile.in index 729917d3..724c34e7 100644 --- a/src/supplicant-manager/Makefile.in +++ b/src/supplicant-manager/Makefile.in @@ -229,6 +229,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index c651e0fa..4860314b 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -123,7 +123,7 @@ nm_supplicant_config_add_option_with_type (NMSupplicantConfig *self, char buf[255]; memset (&buf[0], 0, sizeof (buf)); memcpy (&buf[0], value, len > 254 ? 254 : len); - nm_log_warn (LOGD_SUPPLICANT, "Key '%s' and/or value '%s' invalid.", key, buf); + nm_log_warn (LOGD_SUPPLICANT, "Key '%s' and/or value '%s' invalid.", key, secret ? "<omitted>" : buf); return FALSE; } } diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in index 18288c6e..61f70d7b 100644 --- a/src/supplicant-manager/tests/Makefile.in +++ b/src/supplicant-manager/tests/Makefile.in @@ -188,6 +188,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index 0f19b712..9d848125 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -205,6 +205,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/vpn-manager/Makefile.in b/src/vpn-manager/Makefile.in index 3785667e..02335d88 100644 --- a/src/vpn-manager/Makefile.in +++ b/src/vpn-manager/Makefile.in @@ -190,6 +190,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 067b2dce..75ba6451 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -46,6 +46,7 @@ #include "NetworkManagerUtils.h" #include "nm-dns-manager.h" #include "nm-netlink-monitor.h" +#include "nm-netlink-utils.h" #include "nm-glib-compat.h" #include "settings/nm-settings-connection.h" @@ -86,6 +87,7 @@ typedef struct { NMIP4Config *ip4_config; guint32 ip4_internal_gw; char *ip_iface; + int ip_ifindex; char *banner; struct rtnl_route *gw_route; @@ -424,6 +426,13 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, goto error; } + /* Grab the interface index for address/routing operations */ + priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface); + if (!priv->ip_ifindex) { + nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface); + goto error; + } + addr = nm_ip4_address_new (); nm_ip4_address_set_prefix (addr, 24); /* default to class C */ @@ -529,9 +538,9 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (priv->connection, NM_TYPE_SETTING_IP4_CONFIG)); nm_utils_merge_ip4_config (config, s_ip4); - nm_system_device_set_up_down_with_iface (priv->ip_iface, TRUE, NULL); + nm_system_iface_set_up (priv->ip_ifindex, TRUE, NULL); - if (nm_system_apply_ip4_config (priv->ip_iface, config, 0, NM_IP4_COMPARE_FLAG_ALL)) { + if (nm_system_apply_ip4_config (priv->ip_ifindex, config, 0, NM_IP4_COMPARE_FLAG_ALL)) { NMDnsManager *dns_mgr; /* Add any explicit route to the VPN gateway through the parent device */ @@ -765,6 +774,14 @@ nm_vpn_connection_get_ip_iface (NMVPNConnection *connection) return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip_iface; } +int +nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection) +{ + g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), -1); + + return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip_ifindex; +} + NMDevice * nm_vpn_connection_get_parent_device (NMVPNConnection *connection) { @@ -940,11 +957,11 @@ vpn_cleanup (NMVPNConnection *connection) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - if (priv->ip_iface) { - nm_system_device_set_up_down_with_iface (priv->ip_iface, FALSE, NULL); + if (priv->ip_ifindex) { + nm_system_iface_set_up (priv->ip_ifindex, FALSE, NULL); /* FIXME: use AF_UNSPEC here when we have IPv6 support */ - nm_system_device_flush_routes_with_iface (priv->ip_iface, AF_INET); - nm_system_device_flush_addresses_with_iface (priv->ip_iface); + nm_system_iface_flush_routes (priv->ip_ifindex, AF_INET); + nm_system_iface_flush_addresses (priv->ip_ifindex, AF_UNSPEC); } if (priv->ip4_config) { @@ -958,12 +975,12 @@ vpn_cleanup (NMVPNConnection *connection) /* Remove any previously added VPN gateway host route */ if (priv->gw_route) - rtnl_route_del (nm_netlink_get_default_handle (), priv->gw_route, 0); + nm_netlink_route_delete (priv->gw_route); /* Reset routes and addresses of the currently active device */ parent_config = nm_device_get_ip4_config (priv->parent_dev); if (parent_config) { - if (!nm_system_apply_ip4_config (nm_device_get_ip_iface (priv->parent_dev), + if (!nm_system_apply_ip4_config (nm_device_get_ip_ifindex (priv->parent_dev), nm_device_get_ip4_config (priv->parent_dev), nm_device_get_priority (priv->parent_dev), NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_ROUTES)) { @@ -982,6 +999,7 @@ vpn_cleanup (NMVPNConnection *connection) g_free (priv->ip_iface); priv->ip_iface = NULL; + priv->ip_ifindex = 0; /* Clear out connection secrets to ensure that the settings service * gets asked for them next time the connection is activated. diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index ee8eb5b6..daf9483c 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -72,6 +72,7 @@ void nm_vpn_connection_disconnect (NMVPNConnection *connect NMVPNConnectionStateReason reason); NMIP4Config * nm_vpn_connection_get_ip4_config (NMVPNConnection *connection); const char * nm_vpn_connection_get_ip_iface (NMVPNConnection *connection); +int nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection); NMDevice * nm_vpn_connection_get_parent_device (NMVPNConnection *connection); guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection); diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index 6772bb18..da2cf25f 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2010 Red Hat, Inc. + * Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -306,9 +306,9 @@ nm_vpn_manager_get_active_connections (NMVPNManager *self) return list; } -NMConnection * -nm_vpn_manager_get_connection_for_active (NMVPNManager *manager, - const char *active_path) +NMVPNConnection * +nm_vpn_manager_get_vpn_connection_for_active (NMVPNManager *manager, + const char *active_path) { NMVPNManagerPrivate *priv; GHashTableIter iter; @@ -327,13 +327,24 @@ nm_vpn_manager_get_connection_for_active (NMVPNManager *manager, ac_path = nm_vpn_connection_get_active_connection_path (vpn); if (ac_path && !strcmp (ac_path, active_path)) - return nm_vpn_connection_get_connection (vpn); + return vpn; } } return NULL; } +NMConnection * +nm_vpn_manager_get_connection_for_active (NMVPNManager *manager, + const char *active_path) +{ + NMVPNConnection *vpn_con; + + vpn_con = nm_vpn_manager_get_vpn_connection_for_active (manager, active_path); + + return vpn_con ? nm_vpn_connection_get_connection (vpn_con) : NULL; +} + static char * service_name_from_file (const char *path) { diff --git a/src/vpn-manager/nm-vpn-manager.h b/src/vpn-manager/nm-vpn-manager.h index a899122c..41010323 100644 --- a/src/vpn-manager/nm-vpn-manager.h +++ b/src/vpn-manager/nm-vpn-manager.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2008 Red Hat, Inc. + * Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -83,7 +83,10 @@ void nm_vpn_manager_add_active_connections (NMVPNManager *manager, GSList *nm_vpn_manager_get_active_connections (NMVPNManager *manager); +NMVPNConnection *nm_vpn_manager_get_vpn_connection_for_active (NMVPNManager *manager, + const char *active_path); + NMConnection *nm_vpn_manager_get_connection_for_active (NMVPNManager *manager, const char *active_path); -#endif /* NM_VPN_VPN_MANAGER_H */ +#endif /* NM_VPN_MANAGER_H */ diff --git a/src/wimax/Makefile.in b/src/wimax/Makefile.in index e6064bc6..655eca71 100644 --- a/src/wimax/Makefile.in +++ b/src/wimax/Makefile.in @@ -186,6 +186,12 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ LIBNL_CFLAGS = @LIBNL_CFLAGS@ LIBNL_LIBS = @LIBNL_LIBS@ LIBOBJS = @LIBOBJS@ diff --git a/src/wimax/nm-device-wimax.c b/src/wimax/nm-device-wimax.c index 9dff503d..78651c3b 100644 --- a/src/wimax/nm-device-wimax.c +++ b/src/wimax/nm-device-wimax.c @@ -91,6 +91,9 @@ typedef struct { struct ether_addr hw_addr; guint activation_timeout_id; + /* Track whether stage1 (Prepare) is completed yet or not */ + gboolean prepare_done; + guint sdk_action_defer_id; guint link_timeout_id; @@ -231,27 +234,25 @@ set_current_nsp (NMDeviceWimax *self, NMWimaxNsp *new_nsp) { NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); NMWimaxNsp *old_nsp; - char *old_path = NULL; + gboolean path_changed = FALSE; old_nsp = priv->current_nsp; - if (old_nsp) { - old_path = g_strdup (nm_wimax_nsp_get_dbus_path (old_nsp)); - priv->current_nsp = NULL; - } + priv->current_nsp = NULL; if (new_nsp) priv->current_nsp = g_object_ref (new_nsp); - if (old_nsp) - g_object_unref (old_nsp); + if (old_nsp && new_nsp) { + path_changed = (g_strcmp0 (nm_wimax_nsp_get_dbus_path (old_nsp), + nm_wimax_nsp_get_dbus_path (new_nsp)) != 0); + } /* Only notify if it's really changed */ - if ( (!old_path && new_nsp) - || (old_path && !new_nsp) - || (old_path && new_nsp && strcmp (old_path, nm_wimax_nsp_get_dbus_path (new_nsp)))) + if (old_nsp != new_nsp || path_changed) g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP); - g_free (old_path); + if (old_nsp) + g_object_unref (old_nsp); } NMWimaxNsp * @@ -390,7 +391,7 @@ real_take_down (NMDevice *device) static gboolean real_hw_is_up (NMDevice *device) { - return nm_system_device_is_up (device); + return nm_system_iface_is_up (nm_device_get_ip_ifindex (device)); } static gboolean @@ -401,13 +402,13 @@ real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) if (!priv->enabled || !priv->wimaxd_enabled) return FALSE; - return nm_system_device_set_up_down (dev, TRUE, no_firmware); + return nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware); } static void real_hw_take_down (NMDevice *dev) { - nm_system_device_set_up_down (dev, FALSE, NULL); + nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), FALSE, NULL); } static void @@ -749,6 +750,8 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) set_current_nsp (NM_DEVICE_WIMAX (device), nsp); + priv->prepare_done = TRUE; + /* If the device is scanning, it won't connect, so we have to wait until * it's not scanning to proceed to stage 2. */ @@ -936,7 +939,7 @@ wmx_state_change_cb (struct wmxsdk *wmxsdk, * then check if we need to move to stage2 now that the device might be * ready. */ - if (state == NM_DEVICE_STATE_PREPARE) { + if (state == NM_DEVICE_STATE_PREPARE && priv->prepare_done) { if ( new_status == WIMAX_API_DEVICE_STATUS_Ready || new_status == WIMAX_API_DEVICE_STATUS_Connecting) { nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); @@ -1130,18 +1133,22 @@ wmx_removed_cb (struct wmxsdk *wmxsdk, void *user_data) NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - if (priv->sdk) { - /* Clear callbacks just in case we don't hold the last reference */ - iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); + if (!priv->sdk) { + nm_log_dbg (LOGD_WIMAX, "(%s): removed unhandled WiMAX interface", wmxsdk->ifname); + return; + } - wmxsdk_unref (priv->sdk); - priv->sdk = NULL; + nm_log_dbg (LOGD_WIMAX, "(%s): removed WiMAX interface", wmxsdk->ifname); - priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NONE); - } + /* Clear callbacks just in case we don't hold the last reference */ + iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); + wmxsdk_unref (priv->sdk); + priv->sdk = NULL; + + priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); } /*************************************************************************/ @@ -1277,6 +1284,9 @@ device_state_changed (NMDevice *device, NMDeviceWimax *self = NM_DEVICE_WIMAX (device); NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + /* Reset our stage1 (Prepare) done marker since it's only valid while in stage1 */ + priv->prepare_done = FALSE; + if (new_state < NM_DEVICE_STATE_DISCONNECTED) remove_all_nsps (self); @@ -1323,21 +1333,27 @@ wmx_new_sdk_cb (struct wmxsdk *sdk, void *user_data) NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - /* If we now have the SDK, schedule an idle handler to start the device up */ - if (!priv->sdk) { - priv->sdk = wmxsdk_ref (sdk); - iwmx_sdk_set_callbacks(priv->sdk, - wmx_state_change_cb, - wmx_media_status_cb, - wmx_connect_result_cb, - wmx_scan_result_cb, - wmx_removed_cb, - self); - iwmx_sdk_set_fast_reconnect_enabled (priv->sdk, 0); - - if (!priv->sdk_action_defer_id) - priv->sdk_action_defer_id = g_idle_add (sdk_action_defer_cb, self); + /* We only track one wmxsdk at a time because the WiMAX SDK is pretty stupid */ + if (priv->sdk) { + nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX interface already known", sdk->ifname); + return; } + + nm_log_dbg (LOGD_WIMAX, "(%s): new WiMAX interface (%s)", sdk->ifname, sdk->name); + + /* Now that we have an SDK, schedule an idle handler to start the device up */ + priv->sdk = wmxsdk_ref (sdk); + iwmx_sdk_set_callbacks(priv->sdk, + wmx_state_change_cb, + wmx_media_status_cb, + wmx_connect_result_cb, + wmx_scan_result_cb, + wmx_removed_cb, + self); + iwmx_sdk_set_fast_reconnect_enabled (priv->sdk, 0); + + if (!priv->sdk_action_defer_id) + priv->sdk_action_defer_id = g_idle_add (sdk_action_defer_cb, self); } /*************************************************************************/ |